linuxulator: handle V3 capget/capset
Linux 2.6.26 introduced 64-bit capability sets. Extend our stub implementation to handle both 32- and 64-bit. (We still report no capabilities in capget, and disallow any in capset.) Reviewed by: chuck Sponsored by: Turing Robotic Industries Inc. Differential Revision: https://reviews.freebsd.org/D15887
This commit is contained in:
parent
01cebb69be
commit
aec1e6d390
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=335387
@ -1867,7 +1867,9 @@ linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#define _LINUX_CAPABILITY_VERSION 0x19980330
|
||||
#define _LINUX_CAPABILITY_VERSION_1 0x19980330
|
||||
#define _LINUX_CAPABILITY_VERSION_2 0x20071026
|
||||
#define _LINUX_CAPABILITY_VERSION_3 0x20080522
|
||||
|
||||
struct l_user_cap_header {
|
||||
l_int version;
|
||||
@ -1881,27 +1883,35 @@ struct l_user_cap_data {
|
||||
};
|
||||
|
||||
int
|
||||
linux_capget(struct thread *td, struct linux_capget_args *args)
|
||||
linux_capget(struct thread *td, struct linux_capget_args *uap)
|
||||
{
|
||||
struct l_user_cap_header luch;
|
||||
struct l_user_cap_data lucd;
|
||||
int error;
|
||||
struct l_user_cap_data lucd[2];
|
||||
int error, u32s;
|
||||
|
||||
if (args->hdrp == NULL)
|
||||
if (uap->hdrp == NULL)
|
||||
return (EFAULT);
|
||||
|
||||
error = copyin(args->hdrp, &luch, sizeof(luch));
|
||||
error = copyin(uap->hdrp, &luch, sizeof(luch));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (luch.version != _LINUX_CAPABILITY_VERSION) {
|
||||
switch (luch.version) {
|
||||
case _LINUX_CAPABILITY_VERSION_1:
|
||||
u32s = 1;
|
||||
break;
|
||||
case _LINUX_CAPABILITY_VERSION_2:
|
||||
case _LINUX_CAPABILITY_VERSION_3:
|
||||
u32s = 2;
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
if (ldebug(capget))
|
||||
printf(LMSG("invalid capget capability version 0x%x"),
|
||||
luch.version);
|
||||
#endif
|
||||
luch.version = _LINUX_CAPABILITY_VERSION;
|
||||
error = copyout(&luch, args->hdrp, sizeof(luch));
|
||||
luch.version = _LINUX_CAPABILITY_VERSION_1;
|
||||
error = copyout(&luch, uap->hdrp, sizeof(luch));
|
||||
if (error)
|
||||
return (error);
|
||||
return (EINVAL);
|
||||
@ -1910,42 +1920,50 @@ linux_capget(struct thread *td, struct linux_capget_args *args)
|
||||
if (luch.pid)
|
||||
return (EPERM);
|
||||
|
||||
if (args->datap) {
|
||||
if (uap->datap) {
|
||||
/*
|
||||
* The current implementation doesn't support setting
|
||||
* a capability (it's essentially a stub) so indicate
|
||||
* that no capabilities are currently set or available
|
||||
* to request.
|
||||
*/
|
||||
bzero (&lucd, sizeof(lucd));
|
||||
error = copyout(&lucd, args->datap, sizeof(lucd));
|
||||
memset(&lucd, 0, u32s * sizeof(lucd[0]));
|
||||
error = copyout(&lucd, uap->datap, u32s * sizeof(lucd[0]));
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_capset(struct thread *td, struct linux_capset_args *args)
|
||||
linux_capset(struct thread *td, struct linux_capset_args *uap)
|
||||
{
|
||||
struct l_user_cap_header luch;
|
||||
struct l_user_cap_data lucd;
|
||||
int error;
|
||||
struct l_user_cap_data lucd[2];
|
||||
int error, i, u32s;
|
||||
|
||||
if (args->hdrp == NULL || args->datap == NULL)
|
||||
if (uap->hdrp == NULL || uap->datap == NULL)
|
||||
return (EFAULT);
|
||||
|
||||
error = copyin(args->hdrp, &luch, sizeof(luch));
|
||||
error = copyin(uap->hdrp, &luch, sizeof(luch));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (luch.version != _LINUX_CAPABILITY_VERSION) {
|
||||
switch (luch.version) {
|
||||
case _LINUX_CAPABILITY_VERSION_1:
|
||||
u32s = 1;
|
||||
break;
|
||||
case _LINUX_CAPABILITY_VERSION_2:
|
||||
case _LINUX_CAPABILITY_VERSION_3:
|
||||
u32s = 2;
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
if (ldebug(capset))
|
||||
printf(LMSG("invalid capset capability version 0x%x"),
|
||||
luch.version);
|
||||
#endif
|
||||
luch.version = _LINUX_CAPABILITY_VERSION;
|
||||
error = copyout(&luch, args->hdrp, sizeof(luch));
|
||||
luch.version = _LINUX_CAPABILITY_VERSION_1;
|
||||
error = copyout(&luch, uap->hdrp, sizeof(luch));
|
||||
if (error)
|
||||
return (error);
|
||||
return (EINVAL);
|
||||
@ -1954,18 +1972,21 @@ linux_capset(struct thread *td, struct linux_capset_args *args)
|
||||
if (luch.pid)
|
||||
return (EPERM);
|
||||
|
||||
error = copyin(args->datap, &lucd, sizeof(lucd));
|
||||
error = copyin(uap->datap, &lucd, u32s * sizeof(lucd[0]));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* We currently don't support setting any capabilities. */
|
||||
if (lucd.effective || lucd.permitted || lucd.inheritable) {
|
||||
linux_msg(td,
|
||||
"capset effective=0x%x, permitted=0x%x, "
|
||||
"inheritable=0x%x is not implemented",
|
||||
(int)lucd.effective, (int)lucd.permitted,
|
||||
(int)lucd.inheritable);
|
||||
return (EPERM);
|
||||
for (i = 0; i < u32s; i++) {
|
||||
if (lucd[i].effective || lucd[i].permitted ||
|
||||
lucd[i].inheritable) {
|
||||
linux_msg(td,
|
||||
"capset[%d] effective=0x%x, permitted=0x%x, "
|
||||
"inheritable=0x%x is not implemented", i,
|
||||
(int)lucd[i].effective, (int)lucd[i].permitted,
|
||||
(int)lucd[i].inheritable);
|
||||
return (EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
Loading…
Reference in New Issue
Block a user