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

Reply via email to