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

Detect kernel support of PR_CAP_AMBIENT at runtime #28

Closed
ntkme opened this issue Feb 3, 2021 · 5 comments
Closed

Detect kernel support of PR_CAP_AMBIENT at runtime #28

ntkme opened this issue Feb 3, 2021 · 5 comments

Comments

@ntkme
Copy link
Contributor

ntkme commented Feb 3, 2021

The issue I'm facing is that I have containers build with 5.x kernel headers, and the kernel versions I need to support for actual deployment is ranging between 4.1 - 5.x, which is a mix of kernels that may and may not support PR_CAP_AMBIENT.

Building the support of PR_CAP_AMBIENT then run libcap-ng on kernel without actual support would fail almost every function. Build different versions of containers with different kernel headers is not ideal.

If we can detect the support of PR_CAP_AMBIENT at runtime instead of compile time then we can conditionally run code related to PR_CAP_AMBIENT, thus a single build of libcap-ng using new kernel headers can run on both old and new kernel without causing problem.

I'm not really a C programmer, but I imagine we can do something like this:

#ifdef PR_CAPBSET_DROP
int has_capbset_drop = 1;
rc = prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
if (rc < 0 && errno == EINVAL) { // EINVAL -> kernel does not support PR_CAPBSET_DROP
  has_capbset_drop = 0;
}
if (has_capbset_drop) {
  ...
}
#endif

#ifdef PR_CAP_AMBIENT
int has_ambient = 1;
rc = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, 0, 0, 0);
if (rc < 0 && errno == EINVAL) { // EINVAL -> kernel does not support PR_CAP_AMBIENT
  has_ambient = 0;
}
if (has_ambient) {
  ...
}
#endif

I'd happy to make a PR, but I want to hear some thoughts before I proceed.

@stevegrubb
Copy link
Owner

Hi, thanks for the patch. I'll look into this in a couple days. I agree that runtime detection might be a better way to go.

@stevegrubb
Copy link
Owner

I am readying a new libcap-ng release. I looked at the patch. I would do a couple things different such as declaring the variables static rather than hidden. And there are some style issues such as using all caps for defines rather than variables. Aside from that, I think the patch looks generally good. What I'm considering doing is to just apply the patch "as is" and then put another patch over it fixing the style issues.

@ntkme
Copy link
Contributor Author

ntkme commented Jul 22, 2021

Sounds good. Thanks for looking at this!

@stevegrubb
Copy link
Owner

The patch has been applied. Thanks!

agnostic-apollo added a commit to agnostic-apollo/termux-packages that referenced this issue Dec 10, 2021
Android 7 and some Android devices 8 do not support ambient capabilities
and will return "activate capabilities: Invalid argument" when running
setpriv.

strace shows "prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) = -1 EINVAL (Invalid argument)"
4.3    kernel   PR_CAP_AMBIENT

This was an issue with libcap-ng where support for PR_CAP_AMBIENT was
checked at compile time, so setpriv only worked on Android > 7/8
when `capng_apply()` was called.

https://github.com/util-linux/util-linux/blob/v2.37.1/sys-utils/setpriv.c#L1010
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L59
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L716
https://source.android.com/devices/architecture/kernel/android-common

This has been fixed in libcap-ng by checking PR_CAP_AMBIENT at runtime
with 187ed535. libcap-ng `0.8.3` has not been released yet and so we
use a pre release version.

stevegrubb/libcap-ng#28
stevegrubb/libcap-ng@187ed535
agnostic-apollo added a commit to agnostic-apollo/termux-packages that referenced this issue Dec 10, 2021
Added `setpriv` in `util-linux`.

Android 7 and some Android devices 8 do not support ambient capabilities and will return `activate capabilities: Invalid argument` when running `setpriv`.

strace shows `"prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) = -1 EINVAL (Invalid argument)"`

This was an issue with `libcap-ng` where support for `PR_CAP_AMBIENT` was checked at compile time, so `setpriv` only worked on Android > `7`/`8` when `capng_apply()` was called.

`4.3    kernel   PR_CAP_AMBIENT`

https://github.com/util-linux/util-linux/blob/v2.37.1/sys-utils/setpriv.c#L1010
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L59
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L716
https://source.android.com/devices/architecture/kernel/android-common

This has been fixed in `libcap-ng` by checking `PR_CAP_AMBIENT` at runtime with `187ed535`. `libcap-ng` `0.8.3` has not been released yet and so we use a pre release version `0.8.3~pre1`.

stevegrubb/libcap-ng#28
stevegrubb/libcap-ng@187ed535
agnostic-apollo added a commit to agnostic-apollo/termux-packages that referenced this issue Dec 10, 2021
Added `setpriv` in `util-linux` which requires `libcap-ng` to be updated as well for it work.

Android 7 and some Android devices 8 do not support ambient capabilities and will return `activate capabilities: Invalid argument` when running `setpriv`.

strace shows `"prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) = -1 EINVAL (Invalid argument)"`

This was an issue with `libcap-ng` where support for `PR_CAP_AMBIENT` was checked at compile time, so `setpriv` only worked on Android > `7`/`8` when `capng_apply()` was called.

`4.3    kernel   PR_CAP_AMBIENT`

https://github.com/util-linux/util-linux/blob/v2.37.1/sys-utils/setpriv.c#L1010
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L59
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L716
https://source.android.com/devices/architecture/kernel/android-common

This has been fixed in `libcap-ng` by checking `PR_CAP_AMBIENT` at runtime with `187ed535`. `libcap-ng` `0.8.3` has not been released yet and so we use a pre release version `0.8.3~pre1`.

stevegrubb/libcap-ng#28
stevegrubb/libcap-ng@187ed535
agnostic-apollo added a commit to agnostic-apollo/termux-packages that referenced this issue Dec 11, 2021
Added `setpriv` in `util-linux` which requires `libcap-ng` to be updated as well for it work.

Android 7 and some Android devices 8 do not support ambient capabilities and will return `activate capabilities: Invalid argument` when running `setpriv`.

strace shows `"prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) = -1 EINVAL (Invalid argument)"`

This was an issue with `libcap-ng` where support for `PR_CAP_AMBIENT` was checked at compile time, so `setpriv` only worked on Android > `7`/`8` when `capng_apply()` was called.

`4.3    kernel   PR_CAP_AMBIENT`

https://github.com/util-linux/util-linux/blob/v2.37.1/sys-utils/setpriv.c#L1010
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L59
https://github.com/stevegrubb/libcap-ng/blob/v0.8.2/src/cap-ng.c#L716
https://source.android.com/devices/architecture/kernel/android-common

This has been fixed in `libcap-ng` by checking `PR_CAP_AMBIENT` at runtime with `187ed535`. `libcap-ng` `0.8.3` has not been released yet and so we use a pre release version `0.8.3~pre1`.

stevegrubb/libcap-ng#28
stevegrubb/libcap-ng@187ed535
@agnostic-apollo
Copy link

Thank you both for this. Solved issues for android/termux as well. termux/termux-packages#8198

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 a pull request may close this issue.

3 participants