/proc/kmsg oddness, patch

Topi Miettinen (Topi.Miettinen@medialab.sonera.net)
Sun, 28 Jun 1998 15:05:51 +0300


It would seem like /proc/kmsg would work differently from normal file
regarding open and read.

# ls -l /proc/kmsg /proc/1/environ
-r-------- 1 root root 0 Jun 28 14:52 /proc/1/environ
-r-------- 1 root root 0 Jun 28 14:52 /proc/kmsg
# su - nobody -c 'cat /proc/1/environ'
cat: /proc/1/environ: Permission denied
# su - nobody -c 'cat /proc/kmsg'
cat: /proc/kmsg: Permission denied
# su - nobody -c 'cat -v' </proc/1/environ
HOME=[cut]
# su - nobody -c cat </proc/kmsg
cat: -: Operation not permitted

So, non-root read() from open fd that points to /proc/kmsg fails. This
happens because kmsg_read() calls sys_syslog(2, buf, count), which is
restricted to capable users only.

This untested patch attempts to fix it, but is it the Way?

What I'm really trying to do is getting /sbin/klogd to setuid(kloguser)
after opening /proc/kmsg.

-Topi

diff -ru linux-2.1.107/fs/proc/kmsg.c.orig linux-2.1.107/fs/proc/kmsg.c
--- linux-2.1.107/fs/proc/kmsg.c.orig Fri Feb 27 05:54:49 1998
+++ linux-2.1.107/fs/proc/kmsg.c Sun Jun 28 14:43:51 1998
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>

#include <asm/uaccess.h>
#include <asm/io.h>
@@ -18,6 +19,7 @@
extern struct wait_queue * log_wait;

asmlinkage int sys_syslog(int type, char * bug, int count);
+asmlinkage int read_log(char * buf, int count);

static int kmsg_open(struct inode * inode, struct file * file)
{
@@ -33,7 +35,12 @@
static ssize_t kmsg_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
- return sys_syslog(2,buf,count);
+ int error;
+
+ lock_kernel();
+ error = read_log(buf,count);
+ unlock_kernel();
+ return error;
}

static unsigned int kmsg_poll(struct file *file, poll_table * wait)
diff -ru linux-2.1.107/kernel/printk.c.orig linux-2.1.107/kernel/printk.c
--- linux-2.1.107/kernel/printk.c.orig Wed May 6 20:56:06 1998
+++ linux-2.1.107/kernel/printk.c Sun Jun 28 14:46:53 1998
@@ -108,6 +108,46 @@
c->index = idx;
}

+asmlinkage int read_log(char * buf, int len)
+{
+ unsigned long i;
+ char c;
+ int error = -EINVAL;
+
+ if (!buf || len < 0)
+ goto out;
+ error = 0;
+ if (!len)
+ goto out;
+ error = verify_area(VERIFY_WRITE,buf,len);
+ if (error)
+ goto out;
+ cli();
+ error = -ERESTARTSYS;
+ while (!log_size) {
+ if (signal_pending(current)) {
+ sti();
+ goto out;
+ }
+ interruptible_sleep_on(&log_wait);
+ }
+ i = 0;
+ while (log_size && i < len) {
+ c = *((char *) log_buf+log_start);
+ log_start++;
+ log_size--;
+ log_start &= LOG_BUF_LEN-1;
+ sti();
+ __put_user(c,buf);
+ buf++;
+ i++;
+ cli();
+ }
+ sti();
+ error = i;
+out:
+ return error;
+}

/*
* Commands to sys_syslog:
@@ -139,38 +179,7 @@
case 1: /* Open log */
break;
case 2: /* Read from log */
- error = -EINVAL;
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
- goto out;
- cli();
- error = -ERESTARTSYS;
- while (!log_size) {
- if (signal_pending(current)) {
- sti();
- goto out;
- }
- interruptible_sleep_on(&log_wait);
- }
- i = 0;
- while (log_size && i < len) {
- c = *((char *) log_buf+log_start);
- log_start++;
- log_size--;
- log_start &= LOG_BUF_LEN-1;
- sti();
- __put_user(c,buf);
- buf++;
- i++;
- cli();
- }
- sti();
- error = i;
+ error = read_log(buf, len);
break;
case 4: /* Read/clear last kernel messages */
do_clear = 1;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu