Quoting Andrew Morgan ([EMAIL PROTECTED]): > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Andrew, Serge > > The attached patch (e3d27bcb07485a6c8927c8e4f5483d35a99680c3) adds > 64-bit capability support to the kernel. This version of the patch is > designed to apply against the 2.6.23-mm1 tree. > > FWIW libcap-2.00 supports this change (and earlier capability formats) > > http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/ > > Cheers > > Andrew > > Note: to apply this patch against Linus' upstream kernel, you will first > have to undo this other patch from Serge: > > From b68680e4731abbd78863063aaa0dca2a6d8cc723 Mon Sep 17 00:00:00 2001 > From: Serge E. Hallyn <[EMAIL PROTECTED]> > Date: Sun, 21 Oct 2007 16:41:38 -0700 > Subject: [PATCH] capabilities: clean up file capability reading > > It seems that this patch has made it into 2.6.24-rc1, but it is not > present in 2.6.23-mm1. > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.2.6 (GNU/Linux) > > iD8DBQFHMr5rQheEq9QabfIRAkWuAJ9vQBefhA31KWobFGkIugMnPiS7TwCgkeNg > DXC3U5OPNO/w9ERJBltxMKo= > =SjLL > -----END PGP SIGNATURE-----
> >From e3d27bcb07485a6c8927c8e4f5483d35a99680c3 Mon Sep 17 00:00:00 2001 > From: Andrew G. Morgan <[EMAIL PROTECTED]> > Date: Wed, 7 Nov 2007 23:17:06 -0800 > Subject: [PATCH] Add 64-bit capability support to the kernel. > > The patch has supports legacy (32-bit) capability userspace, and where > possible translates 32-bit capabilities to/from userspace and the VFS > to 64-bit kernel space capabilities. If a capability set cannot be > compressed into 32-bits for consumption by user space, the system call > fails, with -ERANGE. > > FWIW libcap-2.00 supports this change (and earlier capability formats) > > http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/ > > Signed-off-by: Andrew G. Morgan <[EMAIL PROTECTED]> Other than the one comment below, Acked-by: Serge Hallyn <[EMAIL PROTECTED]> > --- > fs/nfsd/auth.c | 10 +- > fs/proc/array.c | 21 +++- > include/linux/capability.h | 222 > +++++++++++++++++++++++++++++++------------- > kernel/capability.c | 89 ++++++++++++++++-- > mm/oom_kill.c | 5 +- > security/commoncap.c | 93 +++++++++++++------ > security/dummy.c | 17 ++- > 7 files changed, 332 insertions(+), 125 deletions(-) > [...] > diff --git a/security/commoncap.c b/security/commoncap.c > index 43f9027..dd63129 100644 > --- a/security/commoncap.c > +++ b/security/commoncap.c > @@ -1,4 +1,4 @@ > -/* Common capabilities, needed by capability.o and root_plug.o > +/* Common capabilities, needed by capability.o and root_plug.o > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > @@ -87,9 +87,9 @@ int cap_capget (struct task_struct *target, kernel_cap_t > *effective, > kernel_cap_t *inheritable, kernel_cap_t *permitted) > { > /* Derived from kernel/capability.c:sys_capget. */ > - *effective = cap_t (target->cap_effective); > - *inheritable = cap_t (target->cap_inheritable); > - *permitted = cap_t (target->cap_permitted); > + *effective = target->cap_effective; > + *inheritable = target->cap_inheritable; > + *permitted = target->cap_permitted; > return 0; > } > > @@ -190,28 +190,54 @@ int cap_inode_killpriv(struct dentry *dentry) > return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); > } > > -static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, > - int size) > +static inline int cap_from_disk(struct vfs_cap_data *caps, > + struct linux_binprm *bprm, unsigned size) Note that you switched this to unsigned, but the caller is still sending in an int (rc). > { > __u32 magic_etc; > + unsigned tocopy, i; > > - if (size != XATTR_CAPS_SZ) > + if (size < sizeof(magic_etc)) { > return -EINVAL; > + } > > - magic_etc = le32_to_cpu(caps[0]); > + magic_etc = le32_to_cpu(caps->magic_etc); > > switch ((magic_etc & VFS_CAP_REVISION_MASK)) { > - case VFS_CAP_REVISION: > - if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) > - bprm->cap_effective = true; > - else > - bprm->cap_effective = false; > - bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); > - bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) ); > - return 0; > + case VFS_CAP_REVISION_1: > + if (size != XATTR_CAPS_SZ_1) { > + return -EINVAL; > + } > + tocopy = VFS_CAP_U32_1; > + break; > + case VFS_CAP_REVISION_2: > + if (size != XATTR_CAPS_SZ_2) { > + return -EINVAL; > + } > + tocopy = VFS_CAP_U32_2; > + break; > default: > return -EINVAL; > } > + > + if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) { > + bprm->cap_effective = true; > + } else { > + bprm->cap_effective = false; > + } > + > + for (i=0; i < tocopy; ++i) { > + bprm->cap_permitted.cap[i] = > + le32_to_cpu(caps->data[i].permitted); > + bprm->cap_inheritable.cap[i] = > + le32_to_cpu(caps->data[i].inheritable); > + } > + while (i < VFS_CAP_U32) { > + bprm->cap_permitted.cap[i] = 0; > + bprm->cap_inheritable.cap[i] = 0; > + i++; > + } > + > + return 0; > } > > /* Locate any VFS capabilities: */ > @@ -219,7 +245,7 @@ static int get_file_caps(struct linux_binprm *bprm) > { > struct dentry *dentry; > int rc = 0; > - __le32 v1caps[XATTR_CAPS_SZ]; > + struct vfs_cap_data vcaps; > struct inode *inode; > > if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { > @@ -232,8 +258,8 @@ static int get_file_caps(struct linux_binprm *bprm) > if (!inode->i_op || !inode->i_op->getxattr) > goto out; > > - rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps, > - XATTR_CAPS_SZ); > + rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps, > + XATTR_CAPS_SZ); > if (rc == -ENODATA || rc == -EOPNOTSUPP) { > /* no data, that's ok */ > rc = 0; > @@ -242,7 +268,7 @@ static int get_file_caps(struct linux_binprm *bprm) > if (rc < 0) > goto out; > > - rc = cap_from_disk(v1caps, bprm, rc); > + rc = cap_from_disk(&vcaps, bprm, rc); > if (rc) > printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", > __FUNCTION__, rc, bprm->filename); > @@ -337,8 +363,11 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, > int unsafe) > * capability rules */ > if (!is_global_init(current)) { > current->cap_permitted = new_permitted; > - current->cap_effective = bprm->cap_effective ? > - new_permitted : 0; > + if (bprm->cap_effective) { > + current->cap_effective = new_permitted; > + } else { > + cap_clear(current->cap_effective); > + } > } > > /* AUD: Audit candidate if current->cap_effective is set */ > @@ -460,13 +489,17 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t > old_euid, uid_t old_suid, > > if (!issecure (SECURE_NO_SETUID_FIXUP)) { > if (old_fsuid == 0 && current->fsuid != 0) { > - cap_t (current->cap_effective) &= > - ~CAP_FS_MASK; > + current->cap_effective = > + cap_drop_fs_set( > + current->cap_effective > + ); > } > if (old_fsuid != 0 && current->fsuid == 0) { > - cap_t (current->cap_effective) |= > - (cap_t (current->cap_permitted) & > - CAP_FS_MASK); > + current->cap_effective = > + cap_raise_fs_set( > + current->cap_effective, > + current->cap_permitted > + ); > } > } > break; > @@ -557,9 +590,9 @@ int cap_task_kill(struct task_struct *p, struct siginfo > *info, > > void cap_task_reparent_to_init (struct task_struct *p) > { > - p->cap_effective = CAP_INIT_EFF_SET; > - p->cap_inheritable = CAP_INIT_INH_SET; > - p->cap_permitted = CAP_FULL_SET; > + cap_set_init_eff(p->cap_effective); > + cap_clear(p->cap_inheritable); > + cap_set_full(p->cap_permitted); > p->keep_capabilities = 0; > return; > } > diff --git a/security/dummy.c b/security/dummy.c > index 6d895ad..bd7e5b3 100644 > --- a/security/dummy.c > +++ b/security/dummy.c > @@ -36,14 +36,19 @@ static int dummy_ptrace (struct task_struct *parent, > struct task_struct *child) > static int dummy_capget (struct task_struct *target, kernel_cap_t * > effective, > kernel_cap_t * inheritable, kernel_cap_t * permitted) > { > - *effective = *inheritable = *permitted = 0; > if (target->euid == 0) { > - *permitted |= (~0 & ~CAP_FS_MASK); > - *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK); > + cap_set_full(*permitted); > + cap_set_init_eff(*effective); > + } else { > + cap_clear(*permitted); > + cap_clear(*effective); > } > - if (target->fsuid == 0) { > - *permitted |= CAP_FS_MASK; > - *effective |= CAP_FS_MASK; > + > + cap_clear(*inheritable); > + > + if (target->fsuid != 0) { > + *permitted = cap_drop_fs_set(*permitted); > + *effective = cap_drop_fs_set(*effective); > } > return 0; > } > -- > 1.5.1.3 > thanks, Andrew. -serge - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html