diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /fs/proc | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 109 | ||||
-rw-r--r-- | fs/proc/fd.c | 1 | ||||
-rw-r--r-- | fs/proc/kmsg.c | 8 | ||||
-rw-r--r-- | fs/proc/link.c | 7 | ||||
-rw-r--r-- | fs/proc/mem.c | 6 | ||||
-rw-r--r-- | fs/proc/openpromfs.c | 124 | ||||
-rw-r--r-- | fs/proc/proc_devtree.c | 7 | ||||
-rw-r--r-- | fs/proc/procfs_syms.c | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 18 |
9 files changed, 231 insertions, 51 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index eeb933628..632d7137c 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -24,11 +24,11 @@ * <Jeff_Tranter@Mitel.COM> * * Bruno Haible : remove 4K limit for the maps file - * <haible@ma2s2.mathematik.uni-karlsruhe.de> + * <haible@ma2s2.mathematik.uni-karlsruhe.de> * * Yves Arrouye : remove removal of trailing spaces in get_array. * <Yves.Arrouye@marin.fdn.fr> - + * * Jerome Forissier : added per-CPU time information to /proc/stat * and /proc/<pid>/cpu extension * <forissier@isia.cma.fr> @@ -37,6 +37,11 @@ * Hans Marcus <crowbar@concepts.nl> * * aeb@cwi.nl : /proc/partitions + * + * + * Alan Cox : security fixes. + * <Alan.Cox@linux.org> + * */ #include <linux/types.h> @@ -578,6 +583,29 @@ static unsigned long get_wchan(struct task_struct *p) fp = *(unsigned long *) (fp - 12); } while (count ++ < 16); } +#elif defined (__sparc__) + { + unsigned long pc, fp, bias = 0; + unsigned long task_base = (unsigned long) p; + struct reg_window *rw; + int count = 0; + +#ifdef __sparc_v9__ + bias = STACK_BIAS; +#endif + fp = p->tss.ksp + bias; + do { + /* Bogus frame pointer? */ + if (fp < (task_base + sizeof(struct task_struct)) || + fp >= (task_base + (2 * PAGE_SIZE))) + break; + rw = (struct reg_window *) fp; + pc = rw->ins[7]; + if (pc < first_sched || pc >= last_sched) + return pc; + fp = rw->ins[6] + bias; + } while (++count < 16); + } #endif return 0; @@ -605,7 +633,7 @@ static unsigned long get_wchan(struct task_struct *p) if ((tsk)->tss.esp0 > PAGE_SIZE && \ MAP_NR((tsk)->tss.esp0) < max_mapnr) \ eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \ - eip; }) + eip; }) #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) #elif defined(__powerpc__) #define KSTK_EIP(tsk) ((tsk)->tss.regs->nip) @@ -695,16 +723,24 @@ static inline const char * get_task_state(struct task_struct *tsk) static inline char * task_state(struct task_struct *p, char *buffer) { + int g; + buffer += sprintf(buffer, "State:\t%s\n" "Pid:\t%d\n" "PPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" - "Gid:\t%d\t%d\t%d\t%d\n", + "Gid:\t%d\t%d\t%d\t%d\n" + "Groups:\t", get_task_state(p), p->pid, p->p_pptr->pid, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); + + for (g = 0; g < p->ngroups; g++) + buffer += sprintf(buffer, "%d ", p->groups[g]); + + buffer += sprintf(buffer, "\n"); return buffer; } @@ -798,9 +834,9 @@ extern inline char *task_cap(struct task_struct *p, char *buffer) return buffer + sprintf(buffer, "CapInh:\t%016x\n" "CapPrm:\t%016x\n" "CapEff:\t%016x\n", - p->cap_inheritable.cap, - p->cap_permitted.cap, - p->cap_effective.cap); + cap_t(p->cap_inheritable), + cap_t(p->cap_permitted), + cap_t(p->cap_effective)); } @@ -866,7 +902,7 @@ static int get_stat(int pid, char * buffer) return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \ -%lu %lu %lu %lu %lu %lu %lu %lu\n", +%lu %lu %lu %lu %lu %lu %lu %lu %d\n", pid, tsk->comm, state, @@ -886,7 +922,7 @@ static int get_stat(int pid, char * buffer) tsk->times.tms_cstime, priority, nice, - tsk->timeout, + 0UL /* removed */, tsk->it_real_value, tsk->start_time, vsize, @@ -907,7 +943,8 @@ static int get_stat(int pid, char * buffer) sigcatch .sig[0] & 0x7fffffffUL, wchan, tsk->nswap, - tsk->cnswap); + tsk->cnswap, + tsk->exit_signal); } static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, @@ -1246,6 +1283,11 @@ static long get_root_array(char * page, int type, char **start, case PROC_PCI: return get_pci_list(page); #endif + +#ifdef CONFIG_NUBUS + case PROC_NUBUS: + return get_nubus_list(page); +#endif case PROC_CPUINFO: return get_cpuinfo(page); @@ -1323,6 +1365,46 @@ static long get_root_array(char * page, int type, char **start, return -EBADF; } +static int process_unauthorized(int type, int pid) +{ + struct task_struct *p; + uid_t euid; /* Save the euid keep the lock short */ + + read_lock(&tasklist_lock); + + /* + * Grab the lock, find the task, save the uid and + * check it has an mm still (ie its not dead) + */ + + p = find_task_by_pid(pid); + if(p) + { + euid=p->euid; + if(!p->mm) /* Scooby scooby doo where are you ? */ + p=NULL; + } + + read_unlock(&tasklist_lock); + + if (!p) + return 1; + + switch(type) + { + case PROC_PID_STATUS: + case PROC_PID_STATM: + case PROC_PID_STAT: + case PROC_PID_MAPS: + case PROC_PID_CMDLINE: + return 0; + } + if(capable(CAP_DAC_OVERRIDE) || current->fsuid == euid) + return 0; + return 1; +} + + static int get_process_array(char * page, int pid, int type) { switch (type) { @@ -1374,6 +1456,13 @@ static ssize_t array_read(struct file * file, char * buf, type &= 0x0000ffff; start = NULL; dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if (pid && process_unauthorized(type, pid)) + { + free_page(page); + return -EIO; + } + if (dp->get_info) length = dp->get_info((char *)page, &start, *ppos, count, 0); diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 5409e2d67..8db99f7f4 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -119,6 +119,7 @@ static int proc_lookupfd(struct inode * dir, struct dentry * dentry) ino = (pid << 16) + PROC_PID_FD_DIR + fd; inode = proc_get_inode(dir->i_sb, ino, NULL); if (inode) { + dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); err = 0; } diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index ff8ec4877..71c5316a9 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -17,23 +17,23 @@ extern unsigned long log_size; extern struct wait_queue * log_wait; -asmlinkage int sys_syslog(int type, char * bug, int count); +extern int do_syslog(int type, char * bug, int count); static int kmsg_open(struct inode * inode, struct file * file) { - return sys_syslog(1,NULL,0); + return do_syslog(1,NULL,0); } static int kmsg_release(struct inode * inode, struct file * file) { - (void) sys_syslog(0,NULL,0); + (void) do_syslog(0,NULL,0); return 0; } static ssize_t kmsg_read(struct file * file, char * buf, size_t count, loff_t *ppos) { - return sys_syslog(2,buf,count); + return do_syslog(2,buf,count); } static unsigned int kmsg_poll(struct file *file, poll_table * wait) diff --git a/fs/proc/link.c b/fs/proc/link.c index df5ea85e6..70c31f21a 100644 --- a/fs/proc/link.c +++ b/fs/proc/link.c @@ -17,7 +17,7 @@ #include <linux/stat.h> static int proc_readlink(struct dentry *, char *, int); -static struct dentry * proc_follow_link(struct dentry *, struct dentry *); +static struct dentry * proc_follow_link(struct dentry *, struct dentry *, unsigned int); /* * links can't do much... @@ -57,7 +57,8 @@ struct inode_operations proc_link_inode_operations = { }; static struct dentry * proc_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct task_struct *p; @@ -172,7 +173,7 @@ static int proc_readlink(struct dentry * dentry, char * buffer, int buflen) { int error; - dentry = proc_follow_link(dentry, NULL); + dentry = proc_follow_link(dentry, NULL, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = -ENOENT; diff --git a/fs/proc/mem.c b/fs/proc/mem.c index 8a8ec9bc0..117587d8d 100644 --- a/fs/proc/mem.c +++ b/fs/proc/mem.c @@ -215,7 +215,7 @@ int mem_mmap(struct file * file, struct vm_area_struct * vma) pgd_t *src_dir, *dest_dir; pmd_t *src_middle, *dest_middle; pte_t *src_table, *dest_table; - unsigned long stmp, dtmp; + unsigned long stmp, dtmp, mapnr; struct vm_area_struct *src_vma = NULL; struct inode *inode = file->f_dentry->d_inode; @@ -296,7 +296,9 @@ int mem_mmap(struct file * file, struct vm_area_struct * vma) set_pte(src_table, pte_mkdirty(*src_table)); set_pte(dest_table, *src_table); - atomic_inc(&mem_map[MAP_NR(pte_page(*src_table))].count); + mapnr = MAP_NR(pte_page(*src_table)); + if (mapnr < max_mapnr) + atomic_inc(&mem_map[MAP_NR(pte_page(*src_table))].count); stmp += PAGE_SIZE; dtmp += PAGE_SIZE; diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c index b3871059e..2c2c84784 100644 --- a/fs/proc/openpromfs.c +++ b/fs/proc/openpromfs.c @@ -1,7 +1,8 @@ -/* $Id: openpromfs.c,v 1.26 1998/01/28 09:55:32 ecd Exp $ +/* $Id: openpromfs.c,v 1.32 1998/11/18 06:15:20 davem Exp $ * openpromfs.c: /proc/openprom handling routines * - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) */ #include <linux/module.h> @@ -27,7 +28,9 @@ typedef struct { typedef struct { #define OPP_STRING 0x10 -#define OPP_BINARY 0x20 +#define OPP_STRINGLIST 0x20 +#define OPP_BINARY 0x40 +#define OPP_HEXSTRING 0x80 #define OPP_DIRTY 0x01 #define OPP_QUOTED 0x02 #define OPP_NOTQUOTED 0x04 @@ -83,7 +86,7 @@ static ssize_t property_read(struct file *filp, char *buf, struct inode *inode = filp->f_dentry->d_inode; int i, j, k; u32 node; - char *p; + char *p, *s; u32 *q; openprom_property *op; char buffer[64]; @@ -129,28 +132,51 @@ static ssize_t property_read(struct file *filp, char *buf, return -EIO; op->value [k] = 0; if (k) { - for (p = op->value; *p >= ' ' && *p <= '~'; p++); - if (p >= op->value + k - 1 && !*p) { - op->flag |= OPP_STRING; - if (p == op->value + k - 1) { - op->flag |= OPP_ASCIIZ; - op->len--; + for (s = 0, p = op->value; p < op->value + k; p++) { + if ((*p >= ' ' && *p <= '~') || *p == '\n') { + op->flag |= OPP_STRING; + s = p; + continue; } - } else if (!(k & 3)) - op->flag |= OPP_BINARY; - else { - printk ("/proc/openprom: Strange property " - "size %d\n", i); - return -EIO; + if (p > op->value && !*p && s == p - 1) { + if (p < op->value + k - 1) + op->flag |= OPP_STRINGLIST; + else + op->flag |= OPP_ASCIIZ; + continue; + } + if (k == 1 && !*p) { + op->flag |= (OPP_STRING|OPP_ASCIIZ); + break; + } + op->flag &= ~(OPP_STRING|OPP_STRINGLIST); + if (k & 3) + op->flag |= OPP_HEXSTRING; + else + op->flag |= OPP_BINARY; + break; } + if (op->flag & OPP_STRINGLIST) + op->flag &= ~(OPP_STRING); + if (op->flag & OPP_ASCIIZ) + op->len--; } } else op = (openprom_property *)filp->private_data; - if (!count || !op->len) return 0; - if (op->flag & OPP_STRING) + if (!count || !(op->len || (op->flag & OPP_ASCIIZ))) + return 0; + if (op->flag & OPP_STRINGLIST) { + for (k = 0, p = op->value; p < op->value + op->len; p++) + if (!*p) + k++; + i = op->len + 4 * k + 3; + } else if (op->flag & OPP_STRING) { i = op->len + 3; - else - i = (op->len * 9)>>2; + } else if (op->flag & OPP_BINARY) { + i = (op->len * 9) >> 2; + } else { + i = (op->len << 1) + 1; + } k = filp->f_pos; if (k >= i) return 0; if (count > i - k) count = i - k; @@ -160,20 +186,48 @@ static ssize_t property_read(struct file *filp, char *buf, k++; count--; } + if (k + count >= i - 2) j = i - 2 - k; else j = count; + if (j >= 0) { copy_to_user(buf + k - filp->f_pos, op->value + k - 1, j); count -= j; k += j; } + if (count) __put_user('\'', &buf [k++ - filp->f_pos]); if (count > 1) __put_user('\n', &buf [k++ - filp->f_pos]); + + } else if (op->flag & OPP_STRINGLIST) { + char *tmp; + + tmp = kmalloc (i, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + s = tmp; + *s++ = '\''; + for (p = op->value; p < op->value + op->len; p++) { + if (!*p) { + strcpy(s, "' + '"); + s += 5; + continue; + } + *s++ = *p; + } + strcpy(s, "'\n"); + + copy_to_user(buf, tmp + k, count); + + kfree(tmp); + k += count; + } else if (op->flag & OPP_BINARY) { char buffer[10]; u32 *first, *last; @@ -205,9 +259,35 @@ static ssize_t property_read(struct file *filp, char *buf, } } } + if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) __put_user('\n', (buf - 1)); + k += count; + + } else if (op->flag & OPP_HEXSTRING) { + char buffer[2]; + + if ((k < i - 1) && (k & 1)) { + sprintf (buffer, "%02x", *(op->value + (k >> 1))); + __put_user(buffer[1], &buf[k++ - filp->f_pos]); + count--; + } + + for (; (count > 1) && (k < i - 1); k += 2) { + sprintf (buffer, "%02x", *(op->value + (k >> 1))); + copy_to_user (buf + k - filp->f_pos, buffer, 2); + count -= 2; + } + + if (count && (k < i - 1)) { + sprintf (buffer, "%02x", *(op->value + (k >> 1))); + __put_user(buffer[0], &buf[k++ - filp->f_pos]); + count--; + } + + if (count) + __put_user('\n', &buf [k++ - filp->f_pos]); } count = k - filp->f_pos; filp->f_pos = k; @@ -742,6 +822,10 @@ static int openpromfs_lookup(struct inode * dir, struct dentry *dentry) inode->i_rdev = d->rdev; break; } + + inode->i_gid = 0; + inode->i_uid = 0; + d_add(dentry, inode); return 0; } diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index c53a440fe..cd4aca324 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -42,7 +42,7 @@ static int property_read_proc(char *page, char **start, off_t off, */ static int devtree_readlink(struct dentry *, char *, int); -static struct dentry *devtree_follow_link(struct dentry *, struct dentry *); +static struct dentry *devtree_follow_link(struct dentry *, struct dentry *, unsigned int); struct inode_operations devtree_symlink_inode_operations = { NULL, /* no file-operations */ @@ -66,7 +66,8 @@ struct inode_operations devtree_symlink_inode_operations = { }; static struct dentry *devtree_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct proc_dir_entry * de; @@ -74,7 +75,7 @@ static struct dentry *devtree_follow_link(struct dentry *dentry, de = (struct proc_dir_entry *) inode->u.generic_ip; link = (char *) de->data; - return lookup_dentry(link, base, 1); + return lookup_dentry(link, base, follow); } static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen) diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c index 6a6ef687e..5537a35e6 100644 --- a/fs/proc/procfs_syms.c +++ b/fs/proc/procfs_syms.c @@ -13,7 +13,9 @@ extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, extern struct inode_operations proc_scsi_inode_operations; extern struct proc_dir_entry proc_sys_root; +#ifdef CONFIG_SYSCTL EXPORT_SYMBOL(proc_sys_root); +#endif EXPORT_SYMBOL(proc_register); EXPORT_SYMBOL(proc_unregister); EXPORT_SYMBOL(create_proc_entry); diff --git a/fs/proc/root.c b/fs/proc/root.c index e2889d123..5f3044f1f 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -55,9 +55,6 @@ static struct file_operations proc_dir_operations = { NULL /* can't fsync */ }; -int proc_readlink(struct dentry * dentry, char * buffer, int buflen); -struct dentry * proc_follow_link(struct dentry *dentry, struct dentry *base); - /* * proc directories can do almost nothing.. */ @@ -388,12 +385,13 @@ static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen) } static struct dentry * proc_self_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { char tmp[30]; sprintf(tmp, "%d", current->pid); - return lookup_dentry(tmp, base, 1); + return lookup_dentry(tmp, base, follow); } int proc_readlink(struct dentry * dentry, char * buffer, int buflen) @@ -420,7 +418,7 @@ int proc_readlink(struct dentry * dentry, char * buffer, int buflen) return len; } -struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base) +struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow) { struct inode *inode = dentry->d_inode; struct proc_dir_entry * de; @@ -435,7 +433,7 @@ struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base) if (de->readlink_proc) len = de->readlink_proc(de, page); - d = lookup_dentry(page, base, 1); + d = lookup_dentry(page, base, follow); free_page((unsigned long) page); return d; } @@ -742,7 +740,7 @@ proc_delete_dentry(struct dentry * dentry) d_drop(dentry); } -static struct dentry_operations proc_dentry_operations = +struct dentry_operations proc_dentry_operations = { NULL, /* revalidate */ NULL, /* d_hash */ @@ -839,6 +837,7 @@ static int proc_root_lookup(struct inode * dir, struct dentry * dentry) inode = proc_get_inode(dir->i_sb, ino, &proc_pid); if (!inode) return -EINVAL; + inode->i_flags|=S_IMMUTABLE; } dentry->d_op = &proc_dentry_operations; @@ -955,6 +954,7 @@ static int proc_root_readdir(struct file * filp, for (i = 0; i < nr_pids; i++) { int pid = pid_array[i]; + ino_t ino = (pid << 16) + PROC_PID_INO; unsigned long j = PROC_NUMBUF; do { @@ -963,7 +963,7 @@ static int proc_root_readdir(struct file * filp, pid /= 10; } while (pid); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0) break; filp->f_pos++; } |