forked from rpms/kernel
		
	Update dmesg_restrict patch to v2
This commit is contained in:
		
							parent
							
								
									967548beda
								
							
						
					
					
						commit
						078da2408e
					
				| @ -1,46 +1,162 @@ | ||||
| From feaf4959c30d0640093a607c577940d3e9351076 Mon Sep 17 00:00:00 2001 | ||||
| From ce10d1b72b4da3c98bbbcb1b945687d964c31923 Mon Sep 17 00:00:00 2001 | ||||
| From: Josh Boyer <jwboyer@redhat.com> | ||||
| Date: Fri, 22 Feb 2013 11:47:37 -0500 | ||||
| Date: Tue, 9 Apr 2013 11:08:13 -0400 | ||||
| Subject: [PATCH] kmsg: Honor dmesg_restrict sysctl on /dev/kmsg | ||||
| 
 | ||||
| Originally, the addition of the dmesg_restrict covered both the syslog | ||||
| method of accessing dmesg, as well as /dev/kmsg itself.  This was done | ||||
| indirectly by security_syslog calling cap_syslog before doing any LSM | ||||
| checks. | ||||
| The dmesg_restrict sysctl currently covers the syslog method for access | ||||
| dmesg, however /dev/kmsg isn't covered by the same protections.  Most | ||||
| people haven't noticed because util-linux dmesg(1) defaults to using the | ||||
| syslog method for access in older versions.  With util-linux dmesg(1) | ||||
| defaults to reading directly from /dev/kmsg. | ||||
| 
 | ||||
| However, commit 12b3052c3ee (capabilities/syslog: open code cap_syslog | ||||
| logic to fix build failure) moved the code around and pushed the checks | ||||
| into the caller itself.  That seems to have inadvertently dropped the | ||||
| checks for dmesg_restrict on /dev/kmsg.  Most people haven't noticed | ||||
| because util-linux dmesg(1) defaults to using the syslog method for | ||||
| access in older versions.  With util-linux 2.22 and a kernel newer than | ||||
| 3.5, dmesg(1) defaults to reading directly from /dev/kmsg. | ||||
| 
 | ||||
| Fix this by making an explicit check in the devkmsg_open function. | ||||
| Fix this by reworking all of the access methods to use the | ||||
| check_syslog_permissions function and adding checks to devkmsg_open and | ||||
| devkmsg_read. | ||||
| 
 | ||||
| This fixes https://bugzilla.redhat.com/show_bug.cgi?id=903192 | ||||
| 
 | ||||
| Reported-by: Christian Kujau <lists@nerdbynature.de> | ||||
| CC: stable@vger.kernel.org | ||||
| Signed-off-by: Eric Paris <eparis@redhat.com> | ||||
| Signed-off-by: Josh Boyer <jwboyer@redhat.com> | ||||
| ---
 | ||||
|  kernel/printk.c | 3 +++ | ||||
|  1 file changed, 3 insertions(+) | ||||
|  kernel/printk.c | 91 +++++++++++++++++++++++++++++---------------------------- | ||||
|  1 file changed, 47 insertions(+), 44 deletions(-) | ||||
| 
 | ||||
| diff --git a/kernel/printk.c b/kernel/printk.c
 | ||||
| index f24633a..398ef9a 100644
 | ||||
| index abbdd9e..5541095 100644
 | ||||
| --- a/kernel/printk.c
 | ||||
| +++ b/kernel/printk.c
 | ||||
| @@ -615,6 +615,9 @@ static int devkmsg_open(struct inode *inode, struct file *file)
 | ||||
|  	struct devkmsg_user *user; | ||||
|  	int err; | ||||
| @@ -368,6 +368,46 @@ static void log_store(int facility, int level,
 | ||||
|  	log_next_seq++; | ||||
|  } | ||||
|   | ||||
| +	if (dmesg_restrict && !capable(CAP_SYSLOG))
 | ||||
| +		return -EACCES;
 | ||||
| +#ifdef CONFIG_SECURITY_DMESG_RESTRICT
 | ||||
| +int dmesg_restrict = 1;
 | ||||
| +#else
 | ||||
| +int dmesg_restrict;
 | ||||
| +#endif
 | ||||
| +
 | ||||
|  	/* write-only does not need any file context */ | ||||
| +static int syslog_action_restricted(int type)
 | ||||
| +{
 | ||||
| +	if (dmesg_restrict)
 | ||||
| +		return 1;
 | ||||
| +	/* Unless restricted, we allow "read all" and "get buffer size" for everybody */
 | ||||
| +	return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static int check_syslog_permissions(int type, bool from_file)
 | ||||
| +{
 | ||||
| +	/*
 | ||||
| +	 * If this is from /proc/kmsg and we've already opened it, then we've
 | ||||
| +	 * already done the capabilities checks at open time.
 | ||||
| +	 */
 | ||||
| +	if (from_file && type != SYSLOG_ACTION_OPEN)
 | ||||
| +		goto ok;
 | ||||
| +
 | ||||
| +	if (syslog_action_restricted(type)) {
 | ||||
| +		if (capable(CAP_SYSLOG))
 | ||||
| +			goto ok;
 | ||||
| +		/* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
 | ||||
| +		if (capable(CAP_SYS_ADMIN)) {
 | ||||
| +			printk_once(KERN_WARNING "%s (%d): "
 | ||||
| +				 "Attempt to access syslog with CAP_SYS_ADMIN "
 | ||||
| +				 "but no CAP_SYSLOG (deprecated).\n",
 | ||||
| +				 current->comm, task_pid_nr(current));
 | ||||
| +			goto ok;
 | ||||
| +		}
 | ||||
| +		return -EPERM;
 | ||||
| +	}
 | ||||
| +ok:
 | ||||
| +	return security_syslog(type);
 | ||||
| +}
 | ||||
| +
 | ||||
|  /* /dev/kmsg - userspace message inject/listen interface */ | ||||
|  struct devkmsg_user { | ||||
|  	u64 seq; | ||||
| @@ -443,10 +483,16 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
 | ||||
|  	char cont = '-'; | ||||
|  	size_t len; | ||||
|  	ssize_t ret; | ||||
| +	int err;
 | ||||
|   | ||||
|  	if (!user) | ||||
|  		return -EBADF; | ||||
|   | ||||
| +	err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
 | ||||
| +		SYSLOG_FROM_FILE);
 | ||||
| +	if (err)
 | ||||
| +		return err;
 | ||||
| +
 | ||||
|  	ret = mutex_lock_interruptible(&user->lock); | ||||
|  	if (ret) | ||||
|  		return ret; | ||||
| @@ -624,7 +670,7 @@ static int devkmsg_open(struct inode *inode, struct file *file)
 | ||||
|  	if ((file->f_flags & O_ACCMODE) == O_WRONLY) | ||||
|  		return 0; | ||||
| -- 
 | ||||
| 1.8.1.2 | ||||
|   | ||||
| -	err = security_syslog(SYSLOG_ACTION_READ_ALL);
 | ||||
| +	err = check_syslog_permissions(SYSLOG_ACTION_OPEN, SYSLOG_FROM_FILE);
 | ||||
|  	if (err) | ||||
|  		return err; | ||||
|   | ||||
| @@ -817,45 +863,6 @@ static inline void boot_delay_msec(int level)
 | ||||
|  } | ||||
|  #endif | ||||
|   | ||||
| -#ifdef CONFIG_SECURITY_DMESG_RESTRICT
 | ||||
| -int dmesg_restrict = 1;
 | ||||
| -#else
 | ||||
| -int dmesg_restrict;
 | ||||
| -#endif
 | ||||
| -
 | ||||
| -static int syslog_action_restricted(int type)
 | ||||
| -{
 | ||||
| -	if (dmesg_restrict)
 | ||||
| -		return 1;
 | ||||
| -	/* Unless restricted, we allow "read all" and "get buffer size" for everybody */
 | ||||
| -	return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
 | ||||
| -}
 | ||||
| -
 | ||||
| -static int check_syslog_permissions(int type, bool from_file)
 | ||||
| -{
 | ||||
| -	/*
 | ||||
| -	 * If this is from /proc/kmsg and we've already opened it, then we've
 | ||||
| -	 * already done the capabilities checks at open time.
 | ||||
| -	 */
 | ||||
| -	if (from_file && type != SYSLOG_ACTION_OPEN)
 | ||||
| -		return 0;
 | ||||
| -
 | ||||
| -	if (syslog_action_restricted(type)) {
 | ||||
| -		if (capable(CAP_SYSLOG))
 | ||||
| -			return 0;
 | ||||
| -		/* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
 | ||||
| -		if (capable(CAP_SYS_ADMIN)) {
 | ||||
| -			printk_once(KERN_WARNING "%s (%d): "
 | ||||
| -				 "Attempt to access syslog with CAP_SYS_ADMIN "
 | ||||
| -				 "but no CAP_SYSLOG (deprecated).\n",
 | ||||
| -				 current->comm, task_pid_nr(current));
 | ||||
| -			return 0;
 | ||||
| -		}
 | ||||
| -		return -EPERM;
 | ||||
| -	}
 | ||||
| -	return 0;
 | ||||
| -}
 | ||||
| -
 | ||||
|  #if defined(CONFIG_PRINTK_TIME) | ||||
|  static bool printk_time = 1; | ||||
|  #else | ||||
| @@ -1131,10 +1138,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 | ||||
|  	if (error) | ||||
|  		goto out; | ||||
|   | ||||
| -	error = security_syslog(type);
 | ||||
| -	if (error)
 | ||||
| -		return error;
 | ||||
| -
 | ||||
|  	switch (type) { | ||||
|  	case SYSLOG_ACTION_CLOSE:	/* Close log */ | ||||
|  		break; | ||||
| -- 
 | ||||
| 1.8.1.4 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user