Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c +++ sys/compat/linux/linux_misc.c @@ -1867,7 +1867,8 @@ /* NOTREACHED */ } -#define _LINUX_CAPABILITY_VERSION 0x19980330 +#define _LINUX_CAPABILITY_VERSION_1 0x19980330 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 struct l_user_cap_header { l_int version; @@ -1881,27 +1882,34 @@ }; 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_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 +1918,49 @@ 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_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 +1969,21 @@ 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++) { + /* We currently don't support setting any capabilities. */ + 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);