/proc/kmsg bug (patches for 2.1.10[78], 2.0.35)

Topi Miettinen (Topi.Miettinen@medialab.sonera.net)
Thu, 16 Jul 1998 22:30:05 +0300


After some weeks of success in a couple of machines running 2.1.107, I'd
like to submit these patches for inclusion in the kernel. As you might
remember (yeah, sure), /proc/kmsg doesn't behave like normal file with
regard to open() and unprivileged read(). The patch moves log reading to a
function of its own, really trivial. 2.0.35 doesn't have [un]lock_kernel()
so those calls are dropped, but otherwise the patch is almost identical.

My goal is getting /sbin/klogd to setuid(kloguser) after opening
/proc/kmsg. If anyone wants to test that, please look at
http://www.debian.org/Bugs/db/24/24326.html for a patch to Debian sysklogd
package.

-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;

--- linux-2.0.35/fs/proc/kmsg.c.orig Fri Dec 22 13:00:19 1995
+++ linux-2.0.35/fs/proc/kmsg.c Thu Jul 16 21:53:25 1998
@@ -17,6 +17,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)
{
@@ -30,7 +31,7 @@

static int kmsg_read(struct inode * inode, struct file * file,char * buf, int count)
{
- return sys_syslog(2,buf,count);
+ return read_log(buf,count);
}

static int kmsg_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
diff -ru linux-2.0.35/kernel/printk.c.orig linux-2.0.35/kernel/printk.c
--- linux-2.0.35/kernel/printk.c.orig Fri Jun 7 11:54:06 1996
+++ linux-2.0.35/kernel/printk.c Thu Jul 16 21:50:44 1998
@@ -45,6 +45,47 @@
static unsigned long log_start = 0;
static unsigned long logged_chars = 0;

+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:
*
@@ -73,35 +114,7 @@
case 1: /* Open log */
return 0;
case 2: /* Read from log */
- if (!buf || len < 0)
- return -EINVAL;
- if (!len)
- return 0;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
- return error;
- cli();
- while (!log_size) {
- if (current->signal & ~current->blocked) {
- sti();
- return -ERESTARTSYS;
- }
- 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();
- return i;
+ return read_log(buf, len);
case 4: /* Read/clear last kernel messages */
do_clear = 1;
/* FALL THRU */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html