diff options
Diffstat (limited to 'kernel/capability.c')
| -rw-r--r-- | kernel/capability.c | 15 | 
1 files changed, 8 insertions, 7 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 4e17041963f..7f876e60521 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -29,7 +29,6 @@ EXPORT_SYMBOL(__cap_empty_set);  EXPORT_SYMBOL(__cap_full_set);  EXPORT_SYMBOL(__cap_init_eff_set); -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  int file_caps_enabled = 1;  static int __init file_caps_disable(char *str) @@ -38,7 +37,6 @@ static int __init file_caps_disable(char *str)  	return 1;  }  __setup("no_file_caps", file_caps_disable); -#endif  /*   * More recent versions of libcap are available from: @@ -169,8 +167,8 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)  	kernel_cap_t pE, pI, pP;  	ret = cap_validate_magic(header, &tocopy); -	if (ret != 0) -		return ret; +	if ((dataptr == NULL) || (ret != 0)) +		return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret;  	if (get_user(pid, &header->pid))  		return -EFAULT; @@ -238,7 +236,7 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)  SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)  {  	struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; -	unsigned i, tocopy; +	unsigned i, tocopy, copybytes;  	kernel_cap_t inheritable, permitted, effective;  	struct cred *new;  	int ret; @@ -255,8 +253,11 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)  	if (pid != 0 && pid != task_pid_vnr(current))  		return -EPERM; -	if (copy_from_user(&kdata, data, -			   tocopy * sizeof(struct __user_cap_data_struct))) +	copybytes = tocopy * sizeof(struct __user_cap_data_struct); +	if (copybytes > sizeof(kdata)) +		return -EFAULT; + +	if (copy_from_user(&kdata, data, copybytes))  		return -EFAULT;  	for (i = 0; i < tocopy; i++) {  |