Skip to content

Commit

Permalink
Add optional security wrapper for stpncpy().
Browse files Browse the repository at this point in the history
This adds support for the optional stpncpy() security wrapper, based
on the _FORTIFY_SOURCE setting.  By default, it only impacts 10.6
builds, though it can be explicitly enabled on 10.5, albeit less
efficiently due to the lack of the compiler builtin.

The stpncpy() function is the only one with an optional security
wrapper which is also optionally provided by legacy-support.  Hence,
this is the only addition needed to close the more general ticket.

Closes: https://trac.macports.org/ticket/69878

Also fixes a minor comment formatting issue.

TESTED:
Tested on 10.4-10.5 ppc, 10.4-10.6 i386, 10.5-10.6 ppc (i386 Rosetta),
10.5-12.x x86_64, 11.x-14.x arm64.
Passes all tests, including newly added tests for this feature.
  • Loading branch information
fhgwright committed May 26, 2024
1 parent 34e47c0 commit 8ccdadd
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 5 deletions.
54 changes: 51 additions & 3 deletions include/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@
#include_next <string.h>

/* stpncpy */
#if __MP_LEGACY_SUPPORT_STPNCPY__
/*
* If we're building with a 10.7+ SDK, stpncpy may have already been defined as
* a macro. In that case, leave it as is. This not only leaves it as provided
* by the SDK, but also informs the decision below.
*/
#if __MP_LEGACY_SUPPORT_STPNCPY__ && !defined(stpncpy)
__MP__BEGIN_DECLS
#undef stpncpy /* In case built with later SDK */
extern char *stpncpy(char *dst, const char *src, size_t n);
__MP__END_DECLS
#endif
#endif /* __MP_LEGACY_SUPPORT_STPNCPY__ && !defined(stpncpy) */

/* strnlen */
#if __MP_LEGACY_SUPPORT_STRNLEN__
Expand All @@ -54,4 +58,48 @@ memmem(const void *l, size_t l_len, const void *s, size_t s_len);
__MP__END_DECLS
#endif

/*
* Security wrapper support
*
* Rather than pushing this off into an added secure/_string.h, we just do it
* here directly.
* If security wrappers are wanted, the SDK string.h has already included
* secure/_common.h, and _USE_FORTIFY_LEVEL has been appropriately defined.
* Otherwise, _USE_FORTIFY_LEVEL is undefined.
*/
#if defined(_USE_FORTIFY_LEVEL) && _USE_FORTIFY_LEVEL > 0

/* stpncpy */
/* Note the defense against building with a 10.7+ SDK, as above. */
#if __MP_LEGACY_SUPPORT_STPNCPY__ && !defined(stpncpy)

/*
* GCC 4.2 for 10.5 lacks __builtin___stpncpy_chk, even though GCC 4.2
* for 10.6 has it. In the absence of a reasonable way to check for compiler
* support directly, we rely on the OS version for the decision. Note that
* the security wrapper mechanism isn't enabled by default on 10.5, anyway,
* but this allows it to work (inefficiently) if it's enabled explicitly.
*/
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060
extern char *__stpncpy_chk(char *dest, const char *src, size_t len,
size_t dstlen);
#define __builtin___stpncpy_chk __stpncpy_chk
#endif /* OS <10.6 */

#define stpncpy(dest, src, len) \
((__darwin_obsz0 (dest) != (size_t) -1) \
? __builtin___stpncpy_chk (dest, src, len, __darwin_obsz (dest)) \
: __inline_stpncpy_chk (dest, src, len))

static __inline char *
__inline_stpncpy_chk (char *__restrict __dest, const char *__restrict __src,
size_t __len)
{
return __builtin___stpncpy_chk (__dest, __src, __len, __darwin_obsz(__dest));
}

#endif /* __MP_LEGACY_SUPPORT_STPNCPY__ && !defined(stpncpy) */

#endif /* _USE_FORTIFY_LEVEL > 0 */

#endif /* _MACPORTS_STRING_H_ */
10 changes: 8 additions & 2 deletions src/stpncpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,26 @@
* @APPLE_LICENSE_HEADER_END@
*/

/*
/*
* NOTICE: This file was modified in April 2024 to allow
* for use as a supporting file for MacPorts legacy support library. This notice
* is included in support of clause 2.2 (b) of the Apple Public License,
* Version 2.0.
*
* The code is almost verbatim from Apple except for the removal of the
* 'restrict' qualifiers for compatibility with pre-C99 compilers.
* 'restrict' qualifiers for compatibility with pre-C99 compilers, and
* the _FORTIFY_SOURCE definition here in lieu of including it as a
* compiler flag (as the Apple build procedure does).
*/

/* MP support header */
#include "MacportsLegacySupport.h"
#if __MP_LEGACY_SUPPORT_STPNCPY__

/* Ensure that we don't use the wrapper macro when defining the function */
#undef _FORTIFY_SOURCE
#define _FORTIFY_SOURCE 0

#include <string.h>

char *
Expand Down
67 changes: 67 additions & 0 deletions src/stpncpy_chk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/

/*
* NOTICE: This file was modified in May 2024 to allow for use as a supporting
* file for MacPorts legacy support library. This notice is included in support
* of clause 2.2 (b) of the Apple Public License, Version 2.0.
*
* The code is almost verbatim from Apple except for:
*
* The correction of the return type.
*
* The removal of the 'restrict' qualifiers for compatibility with
* pre-C99 compilers.
*
* The addition of the missing 'const' qualifier.
*
* The _FORTIFY_SOURCE definition here in lieu of providing it as a
* compiler command-line flag (as the Apple build procedure does).
*/

/* MP support header */
#include "MacportsLegacySupport.h"
/* Note that the support for this mechanism is absent prior to 10.5 */
#if __MP_LEGACY_SUPPORT_STPNCPY__ && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050

/* Ensure that we don't create an infinitely recursive check function */
#undef _FORTIFY_SOURCE
#define _FORTIFY_SOURCE 0

#include <stdlib.h>
#include <string.h>

extern void __chk_fail (void) __attribute__((__noreturn__));

char *
__stpncpy_chk (char *dest, const char *src,
size_t len, size_t dstlen)
{
if (__builtin_expect (dstlen < len, 0))
__chk_fail ();

return stpncpy (dest, src, len);
}

#endif /* __MP_LEGACY_SUPPORT_STPNCPY__ && >= 10.5*/

0 comments on commit 8ccdadd

Please sign in to comment.