Messages in this thread Patch in this message | | | Date | Fri, 23 May 2008 17:02:24 -0700 | From | "Andrew G. Morgan" <> | Subject | Re: capget() overflows buffers. |
| |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Chris Wright wrote: | * 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).
Not really.
libcap2 (the one with 64-bit capability support) continues to work fine (it ships with its own copy of a compatible linux/capability.h, and when I update that, I'll make the corresponding change) but the effect should be transparent to its users:
http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
| That's what I meant earlier by "And use another mechanism to
| signal the availability of 64bit caps."
There is and has always been a method:
~ head.version = 0; ~ getcap(&head, NULL); ~ switch (head.version) { ~ case _LINUX_...: ~ ... ~ break; ~ case _,,,,: ~ etc... ~ break; ~ default: ~ abort("no idea what to do"); ~ }
| 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.
Do any of the above answers help? (FWIW I attached the patch to the redhat bug.)
Cheers Andrew
| | 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; | -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.6 (GNU/Linux)
iD8DBQFIN1sQ+bHCR3gb8jsRAgezAJ0ZRuPNENeHTM46u/LC7IU2++yIowCguMwR GJhKzg7F2p6PcNrKAv9i8Jg= =Mrri -----END PGP SIGNATURE-----
| |