An interesting little patch I knocked up in 10 mins...

Chris Evans (chris@ferret.lmh.ox.ac.uk)
Sat, 25 Jan 1997 20:05:33 +0000 (GMT)


Hi,

The following patch probably has a few mistakes as I don't entirely know
what I'm doing, but the thing is a pretty idea..

It allows the system to respond and store attempted changes to file
permissions on /proc/<pid>. This means that users can 'magically' hide
processes from programs such as top, ps etc., when suitable permissions
are set using chmod.

The ability of people to snoop processes of others has annoyed me a while.
Of course root still sees everything. The default is 'normal' behaviour,
as if the patch was not present. Note that a command such as 'chmod og-rwx
/proc/$$' (where $$ expands to shell process ID) is sufficient to hide all
processes spawned by the shell as the 'process permission' is inherited
from the parent. Similarly, system-wide defaults may be set by messing
with the permissions on /proc/1 (init).

Comments etc.?

Chris.

diff -rubB /home/stuff/kernel/linux/fs/proc/base.c /usr/src/linux/fs/proc/base.c
--- /home/stuff/kernel/linux/fs/proc/base.c Wed Feb 21 09:26:09 1996
+++ /usr/src/linux/fs/proc/base.c Sat Jan 25 19:28:30 1997
@@ -57,6 +57,8 @@

for_each_task(p) {
if (p->pid == pid) {
+ if (ino == PROC_PID_INO)
+ inode->i_mode = p->procperm;
if (p->dumpable || ino == PROC_PID_INO) {
inode->i_uid = p->euid;
inode->i_gid = p->gid;
diff -rubB /home/stuff/kernel/linux/fs/proc/inode.c /usr/src/linux/fs/proc/inode.c
--- /home/stuff/kernel/linux/fs/proc/inode.c Sat Nov 30 10:21:21 1996
+++ /usr/src/linux/fs/proc/inode.c Sat Jan 25 19:30:37 1997
@@ -200,6 +200,7 @@
switch (ino) {
case PROC_PID_INO:
inode->i_nlink = 4;
+ inode->i_mode = p->procperm;
return;
case PROC_PID_MEM:
inode->i_op = &proc_mem_inode_operations;
@@ -252,5 +253,29 @@

void proc_write_inode(struct inode * inode)
{
- inode->i_dirt=0;
+ unsigned long ino,pid;
+ int i;
+ struct task_struct *p;
+
+ inode->i_dirt = 0;
+ ino = inode->i_ino;
+ pid = ino >> 16;
+ ino &= 0x0000ffff;
+
+ if (!pid)
+ return;
+
+ p = task[0];
+ for (i = 0; i < NR_TASKS; i++)
+ if ((p = task[i]) && (p->pid == pid))
+ break;
+ if (!p || i >= NR_TASKS)
+ return;
+
+ switch (ino) {
+ case PROC_PID_INO:
+ p->procperm = ((inode->i_mode & (S_IRUGO | S_IXUGO)) | S_IFDIR);
+ break;
+ }
+ return;
}
diff -rubB /home/stuff/kernel/linux/include/linux/sched.h /usr/src/linux/include/linux/sched.h
--- /home/stuff/kernel/linux/include/linux/sched.h Sun Dec 1 17:59:18 1996
+++ /usr/src/linux/include/linux/sched.h Sat Jan 25 19:32:48 1997
@@ -17,6 +17,7 @@
#include <linux/personality.h>
#include <linux/tasks.h>
#include <linux/kernel.h>
+#include <linux/stat.h>

#include <asm/system.h>
#include <asm/semaphore.h>
@@ -208,6 +209,7 @@
*/
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
struct wait_queue *wait_chldexit; /* for wait4() */
+ mode_t procperm;
unsigned short uid,euid,suid,fsuid;
unsigned short gid,egid,sgid,fsgid;
unsigned long timeout, policy, rt_priority;
@@ -292,6 +294,7 @@
/* pid etc.. */ 0,0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \
/* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \
+/* procperm */ (S_IFDIR | S_IRUGO | S_IXUGO), \
/* uid etc */ 0,0,0,0,0,0,0,0, \
/* timeout */ 0,SCHED_OTHER,0,0,0,0,0,0,0, \
/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \