Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c18n: New {get,set}context APIs for libunwind #2123

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open

Conversation

dpgao
Copy link
Contributor

@dpgao dpgao commented Jun 20, 2024

See also #2122 for a draft of this PR.

_rtld_unw_getcontext_epilogue is removed because when c18n is not enabled, the trusted stack field of the context is unused anyway, so there's no need to fill it.

The assembly stub in _rtld_unw_setcontext is removed because _rtld_unw_setcontext is now expected to be called before all registers are restored, so it does not need to restore any register anymore.

@dstolfa
Copy link
Contributor

dstolfa commented Jun 20, 2024

This makes changes in setjmp/longjmp as well and the commit message should probably reflect that.

Copy link
Collaborator

@bsdjhb bsdjhb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly some text in the commit log explaining why setjmp/longjmp are changing would be good.

#if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX)
mov c2, c8
#else
#if !defined(__CHERI_PURE_CAPABILITY__) || !defined(RTLD_SANDBOX)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it easier to read as !(purecap && sandbox) rather than !purecap || !sandbox.

Copy link
Collaborator

@bsdjhb bsdjhb Jul 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is RTLD_SANDBOX ever true for !purecap? That is, can we simplify some of the #ifdef's to #ifdef RTLD_SANDBOX or #ifndef RTLD_SANDBOX?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is RTLD_SANDBOX ever true for !purecap? That is, can we simplify some of the #ifdef's to #ifdef RTLD_SANDBOX or #ifndef RTLD_SANDBOX?

The purecap check is indeed redundant. I'll do a find-and-replace once the libsys is merged. (libsys renames RTLD_SANDBOX to CHERI_LIB_C18N.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bsdjhb I've removed the checks for __CHERI_PURE_CAPABILITY__ in #2200.

bsdjhb pushed a commit to bsdjhb/cheribsd that referenced this pull request Aug 20, 2024
Security fixes:
 CTSRD-CHERI#2135 rar: Fix OOB in rar e8 filter (CVE-2024-26256)
 CTSRD-CHERI#2145 zip: Fix out of boundary access

Important bugfixes:
 CTSRD-CHERI#2131 7zip: Limit amount of properties
 CTSRD-CHERI#2110 bsdtar: Fix error handling around strtol() usages
 CTSRD-CHERI#2116 passphrase: Never allow empty passwords
 CTSRD-CHERI#2124 rar: Fix "File CRC Error" when extracting specific rar4 archives
 CTSRD-CHERI#2123 xar: Avoid infinite link loop
 CTSRD-CHERI#2108 zip: Update AppleDouble support for directories
 CTSRD-CHERI#2071 zstd: Implement core detection

Obained from:		libarchive
Libarchive commit:	313aa1fa10b657de791e3202c168a6c833bc3543
bsdjhb pushed a commit to bsdjhb/cheribsd that referenced this pull request Aug 20, 2024
Libarchive 3.7.4 + three fixes from master

Security fixes:
 CTSRD-CHERI#2135 rar: Fix OOB in rar e8 filter (CVE-2024-26256)
 CTSRD-CHERI#2145 zip: Fix out of boundary access
 CTSRD-CHERI#2148 rar: Fix OOB in rar delta filter
 CTSRD-CHERI#2149 rar: Fix OOB in rar audio filter

Important bugfixes:
 CTSRD-CHERI#2131 7zip: Limit amount of properties
 CTSRD-CHERI#2110 bsdtar: Fix error handling around strtol() usages
 CTSRD-CHERI#2116 passphrase: Never allow empty passwords
 CTSRD-CHERI#2124 rar: Fix "File CRC Error" when extracting specific rar4 archives
 CTSRD-CHERI#2123 xar: Avoid infinite link loop
 CTSRD-CHERI#2150 xar: Fix another infinite loop and expat error handling
 CTSRD-CHERI#2108 zip: Update AppleDouble support for directories
 CTSRD-CHERI#2071 zstd: Implement core detectiongit

PR:		278588 (exp-run)
MFC after:	1 day
bsdjhb pushed a commit to bsdjhb/cheribsd that referenced this pull request Aug 20, 2024
Libarchive 3.7.4 + three fixes from master

Security fixes:
 CTSRD-CHERI#2135 rar: Fix OOB in rar e8 filter (CVE-2024-26256)
 CTSRD-CHERI#2145 zip: Fix out of boundary access
 CTSRD-CHERI#2148 rar: Fix OOB in rar delta filter
 CTSRD-CHERI#2149 rar: Fix OOB in rar audio filter

Important bugfixes:
 CTSRD-CHERI#2131 7zip: Limit amount of properties
 CTSRD-CHERI#2110 bsdtar: Fix error handling around strtol() usages
 CTSRD-CHERI#2116 passphrase: Never allow empty passwords
 CTSRD-CHERI#2124 rar: Fix "File CRC Error" when extracting specific rar4 archives
 CTSRD-CHERI#2123 xar: Avoid infinite link loop
 CTSRD-CHERI#2150 xar: Fix another infinite loop and expat error handling
 CTSRD-CHERI#2108 zip: Update AppleDouble support for directories
 CTSRD-CHERI#2071 zstd: Implement core detectiongit

PR:		278588 (exp-run)
MFC after:	1 day
@dpgao dpgao requested review from jrtc27 and dstolfa August 22, 2024 19:46
Copy link
Contributor

@dstolfa dstolfa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builds & runs fine, similar to CTSRD-CHERI/llvm-project#740 just a few nits.

libexec/rtld-elf/rtld_c18n.h Outdated Show resolved Hide resolved
libexec/rtld-elf/rtld_c18n.h Show resolved Hide resolved

static void *
unwind_cursor(void)
bool c18n_is_enabled(void);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably be in sys/sys/link_elf.h with dl_iterate_phdr and friends.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Although I guess it would require renaming struct trusted_frame etc. to have a dl_ prefix?

Copy link
Contributor Author

@dpgao dpgao Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, since a struct trusted_frame * only ever leaves RTLD as a sealed capability, a void * should be sufficient.

libexec/rtld-elf/rtld_c18n.c Outdated Show resolved Hide resolved
lib/libc/aarch64/gen/_setjmp.S Show resolved Hide resolved
@@ -217,8 +259,8 @@ func_sig_legal(struct func_sig sig)
/*
* This macro can only be used in a function directly invoked by a trampoline.
*/
#define c18n_return_address() \
(C18N_ENABLED ? get_trusted_stk()->pc : __builtin_return_address(0))
#define c18n_return_address() (C18N_ENABLED ? \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should probably be a non-c18n fallback implementation of this so you don't need to ifdef every use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in another PR

@@ -936,13 +913,17 @@ unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target)
struct trusted_frame *cur, *tf;
sigset_t nset, oset;

if (!C18N_ENABLED)
return (ret);

/*
* Make the function re-entrant by blocking all signals.
*/
SIGFILLSET(nset);
sigprocmask(SIG_SETMASK, &nset, &oset);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could expose functions from rtld_lock.c that use sigfastblock when available, saves having to do syscalls here for single-threaded applications. In theory one could also register a per-thread mask just for c18n to use, given rtld unregisters its locking one when a thread is created. But not for this PR.

@dpgao
Copy link
Contributor Author

dpgao commented Aug 28, 2024

@jrtc27 I've changed how setjmp/longjmp invokes the RTLD's unwinding APIs such that it is very simple to remove the ifdefs in a future PR (essentially we just need a noop ASM stub like in libunwind). I also added dl_ prefixes to the APIs and exported them in link_elf.h.

@dpgao
Copy link
Contributor Author

dpgao commented Aug 29, 2024

The dl_* functions now use the normal ABI and CTSRD-CHERI/llvm-project#740 has been updated accordingly.

@jrtc27
Copy link
Member

jrtc27 commented Aug 29, 2024

Can we keep the old interfaces implemented as compatibility shims so upgrades work when c18n is enabled?

@dpgao
Copy link
Contributor Author

dpgao commented Aug 30, 2024

Can we keep the old interfaces implemented as compatibility shims so upgrades work when c18n is enabled?

It seems that preserving the old interfaces implies retaining much of the old implementation as well (including the assembly stubs), but that's fine.

sys/sys/link_elf.h Outdated Show resolved Hide resolved
}

/*
* XXX: These functions are kept here for compatibility with old libunwind.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libc and libunwind (ditto for the other instance below)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe group all the compat interfaces together at the end?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible to move all the function definitions to the end, but the declaration of _rtld_unw_setcontext_impl has to stay in front because of the function-pointer workaround employed in the previous release. _rtld_unw_setcontext_impl has to be wrapped into _rtld_unw_setcontext_ptr in c18n_init2.

@dpgao dpgao force-pushed the c18n-unw-real branch 2 times, most recently from b36ee3e to 7d7f130 Compare October 18, 2024 21:04
lib/libgcc_s/Makefile Show resolved Hide resolved
lib/libc/gen/dlfcn.c Show resolved Hide resolved
sys/sys/link_elf.h Outdated Show resolved Hide resolved
@jrtc27
Copy link
Member

jrtc27 commented Oct 28, 2024

Be very careful about git subrepo commits in a PR, the parent commit is recorded so rebasing breaks them for next time someone uses git subrepo.

@bsdjhb
Copy link
Collaborator

bsdjhb commented Oct 28, 2024

I'm in the middle of another FreeBSD merge, but I can do an update of libunwind after that so long as the new libunwind will still work fine with the current dev

@jrtc27
Copy link
Member

jrtc27 commented Oct 28, 2024

Yeah, it would be easiest if we decoupled rtld and libunwind changes. Because this PR keeps the old rtld interfaces (and they’ll stay for one release) we don’t need to import libunwind in this PR, we can just merge the new interfaces ready for a future import.

@jrtc27
Copy link
Member

jrtc27 commented Oct 28, 2024

(But note that updating libunwind in dev now would break)

@dpgao
Copy link
Contributor Author

dpgao commented Oct 28, 2024

Be very careful about git subrepo commits in a PR, the parent commit is recorded so rebasing breaks them for next time someone uses git subrepo.

I see. I've removed the subrepo pull commit.

Using relational operators to compare pointers to different trusted
frames is undefined behaviour.
Previously, libunwind hard-codes knowledge about the layout of the
trusted frame and has read access to the trusted stack. This is fragile
and insecure.

Now, the task of extracting the relevant registers from the trusted
stack is delegated to RTLD, and libunwind no longer has access to the
trusted stack.

The unified unwinding APIs are declared as dl_c18n_* functions in
link.h. setjmp/longjmp have been updated to use them.

The previous API has been retained for compatibility with old libunwind.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants