Messages in this thread Patch in this message | | | Date | Fri, 23 May 2008 11:26:02 -0700 | From | Chris Wright <> | Subject | Re: capget() overflows buffers. |
| |
* Andrew G. Morgan (morgan@kernel.org) wrote: > diff --git a/include/linux/capability.h b/include/linux/capability.h > index f4ea0dd..f88b4db 100644 > --- a/include/linux/capability.h > +++ b/include/linux/capability.h > @@ -34,9 +34,6 @@ struct task_struct; > #define _LINUX_CAPABILITY_VERSION_2 0x20071026 > #define _LINUX_CAPABILITY_U32S_2 2 > > -#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 > -#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2 > - > typedef struct __user_cap_header_struct { > __u32 version; > int pid; > @@ -77,10 +74,23 @@ struct vfs_cap_data { > } data[VFS_CAP_U32]; > }; > > -#ifdef __KERNEL__ > +#ifndef __KERNEL__ > + > +/* > + * Backwardly compatible definition for source code - trapped in a > + * 32-bit world. If you find you need this, please consider using > + * libcap to untrap yourself... > + */ > +#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1 > +#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
I'm sure you're painfully aware, but this will need some change to libcap as well (to let it handle 64bit caps again).
That's what I meant earlier by "And use another mechanism to signal the availability of 64bit caps."
All looks good. I think we need to issue some warnings, because at least Fedora 9 and openSUSE 11 are/will be 2.6.25 based.
Something like this:
--- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -31,9 +31,13 @@ struct task_struct; #define _LINUX_CAPABILITY_VERSION_1 0x19980330 #define _LINUX_CAPABILITY_U32S_1 1 +/* v2 should be considered broken */ #define _LINUX_CAPABILITY_VERSION_2 0x20071026 #define _LINUX_CAPABILITY_U32S_2 2 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#define _LINUX_CAPABILITY_U32S_3 2 + typedef struct __user_cap_header_struct { __u32 version; int pid; @@ -86,8 +90,8 @@ struct vfs_cap_data { #else -#define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 -#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2 +#define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 +#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 typedef struct kernel_cap_struct { __u32 cap[_KERNEL_CAPABILITY_U32S]; --- a/kernel/capability.c +++ b/kernel/capability.c @@ -39,6 +39,19 @@ EXPORT_SYMBOL(__cap_init_eff_set); * http://www.kernel.org/pub/linux/libs/security/linux-privs/ */ +static void warn_broken_capability_use(void) +{ + static int warned; + if (!warned) { + char name[sizeof(current->comm)]; + + printk(KERN_INFO "warning: `%s' uses a capabilities version" + " which could be broken if it is not using libcap.\n", + get_task_comm(name, current)); + warned = 1; + } +} + static void warn_legacy_capability_use(void) { static int warned; @@ -85,8 +98,12 @@ asmlinkage long sys_capget(cap_user_head tocopy = _LINUX_CAPABILITY_U32S_1; break; case _LINUX_CAPABILITY_VERSION_2: + warn_broken_capability_use(); tocopy = _LINUX_CAPABILITY_U32S_2; break; + case _LINUX_CAPABILITY_VERSION_3: + tocopy = _LINUX_CAPABILITY_U32S_3; + break; default: if (put_user(_KERNEL_CAPABILITY_VERSION, &header->version)) return -EFAULT; @@ -257,8 +274,12 @@ asmlinkage long sys_capset(cap_user_head tocopy = _LINUX_CAPABILITY_U32S_1; break; case _LINUX_CAPABILITY_VERSION_2: + warn_broken_capability_use(); tocopy = _LINUX_CAPABILITY_U32S_2; break; + case _LINUX_CAPABILITY_VERSION_3: + tocopy = _LINUX_CAPABILITY_U32S_3; + break; default: if (put_user(_KERNEL_CAPABILITY_VERSION, &header->version)) return -EFAULT;
| |