diff -rc2P linux-2.4.17ctx-5/Makefile linux-2.4.17ctx-6/Makefile *** linux-2.4.17ctx-5/Makefile Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/Makefile Tue Jan 8 23:35:19 2002 *************** *** 2,6 **** PATCHLEVEL = 4 SUBLEVEL = 17 ! EXTRAVERSION =ctx-5 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) --- 2,6 ---- PATCHLEVEL = 4 SUBLEVEL = 17 ! EXTRAVERSION =ctx-6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -rc2P linux-2.4.17ctx-5/fs/devpts/inode.c linux-2.4.17ctx-6/fs/devpts/inode.c *** linux-2.4.17ctx-5/fs/devpts/inode.c Wed Oct 10 11:58:19 2001 --- linux-2.4.17ctx-6/fs/devpts/inode.c Sun Jan 27 00:34:45 2002 *************** *** 25,28 **** --- 25,29 ---- #include #include + #include #include "devpts_i.h" *************** *** 153,157 **** inode->i_fop = &devpts_root_operations; inode->i_nlink = 2; - s->u.generic_sbp = (void *) sbi; s->s_blocksize = 1024; --- 154,157 ---- *************** *** 181,184 **** --- 181,197 ---- static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE); + static int devpts_tty_permission(struct inode *inode, int mask) + { + int ret = -EACCES; + if (current->s_context == inode->u.devpts_i.s_context){ + ret = vfs_permission(inode, mask); + } + return ret; + } + + struct inode_operations devpts_tty_inode_operations = { + permission: devpts_tty_permission, + }; + void devpts_pty_new(int number, kdev_t device) { *************** *** 199,202 **** --- 212,217 ---- inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->u.devpts_i.s_context = current->s_context; + inode->i_op = &devpts_tty_inode_operations; init_special_inode(inode, S_IFCHR|sbi->mode, kdev_t_to_nr(device)); diff -rc2P linux-2.4.17ctx-5/fs/devpts/root.c linux-2.4.17ctx-6/fs/devpts/root.c *** linux-2.4.17ctx-5/fs/devpts/root.c Sat Dec 22 22:38:37 2001 --- linux-2.4.17ctx-6/fs/devpts/root.c Sun Jan 27 00:34:20 2002 *************** *** 15,18 **** --- 15,19 ---- #include #include + #include #include "devpts_i.h" *************** *** 65,69 **** while ( nr - 2 < sbi->max_ptys ) { int ptynr = nr - 2; ! if ( sbi->inodes[ptynr] ) { genptsname(numbuf, ptynr); if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 ) --- 66,72 ---- while ( nr - 2 < sbi->max_ptys ) { int ptynr = nr - 2; ! struct inode *inode = sbi->inodes[ptynr]; ! if ( inode != NULL ! && inode->u.devpts_i.s_context == current->s_context ) { genptsname(numbuf, ptynr); if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 ) *************** *** 101,104 **** --- 104,108 ---- int i; const char *p; + struct inode *inode; dentry->d_op = &devpts_dentry_operations; *************** *** 127,135 **** return NULL; ! if ( sbi->inodes[entry] ) ! atomic_inc(&sbi->inodes[entry]->i_count); ! d_add(dentry, sbi->inodes[entry]); return NULL; } --- 131,146 ---- return NULL; ! inode = sbi->inodes[entry]; ! if (inode != NULL ! && inode->u.devpts_i.s_context == current->s_context){ ! atomic_inc(&inode->i_count); ! }else{ ! inode = NULL; ! } ! d_add(dentry, inode); return NULL; } + + diff -rc2P linux-2.4.17ctx-5/fs/namei.c linux-2.4.17ctx-6/fs/namei.c *** linux-2.4.17ctx-5/fs/namei.c Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/fs/namei.c Wed Jan 23 22:41:06 2002 *************** *** 152,155 **** --- 152,162 ---- umode_t mode = inode->i_mode; + /* + A dir with permission bit all 0s is a dead zone for + process running in a vserver. By doing + chmod 000 /vservers + you fix the "escape from chroot" bug. + */ + if ((mode & 0777) == 0 && current->s_context != 0) return -EACCES; if (mask & MAY_WRITE) { /* diff -rc2P linux-2.4.17ctx-5/fs/proc/array.c linux-2.4.17ctx-6/fs/proc/array.c *** linux-2.4.17ctx-5/fs/proc/array.c Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/fs/proc/array.c Sun Jan 27 15:23:51 2002 *************** *** 148,153 **** { int g; ! read_lock(&tasklist_lock); buffer += sprintf(buffer, "State:\t%s\n" --- 148,156 ---- { int g; ! pid_t ppid; read_lock(&tasklist_lock); + ppid = p->p_opptr->pid; + if (current->s_info != NULL + && current->s_info->initpid == ppid) ppid = 1; buffer += sprintf(buffer, "State:\t%s\n" *************** *** 159,163 **** "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), p->tgid, ! p->pid, p->pid ? p->p_opptr->pid : 0, 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); --- 162,166 ---- "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), p->tgid, ! p->pid, p->pid ? ppid : 0, 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); *************** *** 299,305 **** --- 302,311 ---- buffer += sprintf (buffer,"ctxflags: %d\n" ,task->s_info->flags); + buffer += sprintf (buffer,"initpid: %d\n" + ,task->s_info->initpid); }else{ buffer += sprintf (buffer,"ctxticks: none\n"); buffer += sprintf (buffer,"ctxflags: none\n"); + buffer += sprintf (buffer,"initpid: none\n"); } #if defined(CONFIG_ARCH_S390) *************** *** 356,359 **** --- 362,367 ---- read_lock(&tasklist_lock); ppid = task->pid ? task->p_opptr->pid : 0; + if (current->s_info != NULL + && current->s_info->initpid == ppid) ppid = 1; read_unlock(&tasklist_lock); res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ diff -rc2P linux-2.4.17ctx-5/fs/proc/base.c linux-2.4.17ctx-6/fs/proc/base.c *** linux-2.4.17ctx-5/fs/proc/base.c Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/fs/proc/base.c Sun Jan 27 15:01:44 2002 *************** *** 1028,1031 **** --- 1028,1034 ---- && current->s_context != 1 && p->s_context != current->s_context) continue; + /* We hide the fakeinit process since we show it as process 1 */ + if (current->s_info != NULL + && current->s_info->initpid == pid) continue; if (--index >= 0) continue; diff -rc2P linux-2.4.17ctx-5/include/linux/devpts_fs_info.h linux-2.4.17ctx-6/include/linux/devpts_fs_info.h *** linux-2.4.17ctx-5/include/linux/devpts_fs_info.h Wed Dec 31 19:00:00 1969 --- linux-2.4.17ctx-6/include/linux/devpts_fs_info.h Thu Jan 24 23:28:00 2002 *************** *** 0 **** --- 1,4 ---- + struct devpts_inode_info{ + int s_context; + }; + diff -rc2P linux-2.4.17ctx-5/include/linux/fs.h linux-2.4.17ctx-6/include/linux/fs.h *** linux-2.4.17ctx-5/include/linux/fs.h Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/include/linux/fs.h Thu Jan 24 23:27:35 2002 *************** *** 318,321 **** --- 318,322 ---- #include #include + #include /* *************** *** 509,512 **** --- 510,514 ---- struct usbdev_inode_info usbdev_i; struct jffs2_inode_info jffs2_i; + struct devpts_inode_info devpts_i; void *generic_ip; } u; diff -rc2P linux-2.4.17ctx-5/include/linux/sched.h linux-2.4.17ctx-6/include/linux/sched.h *** linux-2.4.17ctx-5/include/linux/sched.h Sun Jan 13 21:17:40 2002 --- linux-2.4.17ctx-6/include/linux/sched.h Thu Jan 24 23:30:50 2002 *************** *** 287,290 **** --- 287,293 ---- #define S_CTX_INFO_NPROC 4 /* Limit number of processes in a context */ #define S_CTX_INFO_PRIVATE 8 /* Noone can join this security context */ + #define S_CTX_INFO_INIT 16 /* This process wants to become the */ + /* logical process 1 of the security */ + /* context */ *************** *** 297,300 **** --- 300,305 ---- atomic_t ticks; /* Number of ticks used by all process */ /* in the s_context */ + int initpid; /* PID of the logical process 1 of the */ + /* of the context */ }; diff -rc2P linux-2.4.17ctx-5/ipc/util.c linux-2.4.17ctx-6/ipc/util.c *** linux-2.4.17ctx-5/ipc/util.c Sun Aug 12 20:37:53 2001 --- linux-2.4.17ctx-6/ipc/util.c Thu Jan 24 16:28:58 2002 *************** *** 94,97 **** --- 94,98 ---- for (id = 0; id <= ids->max_id; id++) { + if (ids->entries[id].s_context != current->s_context) continue; p = ids->entries[id].p; if(p==NULL) *************** *** 168,171 **** --- 169,173 ---- spin_lock(&ids->ary); ids->entries[id].p = new; + ids->entries[id].s_context = current->s_context; return id; } diff -rc2P linux-2.4.17ctx-5/ipc/util.h linux-2.4.17ctx-6/ipc/util.h *** linux-2.4.17ctx-5/ipc/util.h Mon Feb 19 13:18:18 2001 --- linux-2.4.17ctx-6/ipc/util.h Sun Jan 27 00:51:19 2002 *************** *** 26,29 **** --- 26,30 ---- struct ipc_id { struct kern_ipc_perm* p; + int s_context; // Context owning this ID }; *************** *** 75,80 **** spin_lock(&ids->ary); out = ids->entries[lid].p; ! if(out==NULL) spin_unlock(&ids->ary); return out; } --- 76,85 ---- spin_lock(&ids->ary); out = ids->entries[lid].p; ! if(out==NULL ! || (ids->entries[lid].s_context != current->s_context ! && current->s_context != 1)){ spin_unlock(&ids->ary); + out = NULL; + } return out; } diff -rc2P linux-2.4.17ctx-5/kernel/exit.c linux-2.4.17ctx-6/kernel/exit.c *** linux-2.4.17ctx-5/kernel/exit.c Sun Jan 13 21:17:41 2002 --- linux-2.4.17ctx-6/kernel/exit.c Wed Jan 9 23:13:43 2002 *************** *** 158,164 **** { struct task_struct * p; read_lock(&tasklist_lock); ! for_each_task(p) { if (p->p_opptr == father) { --- 158,172 ---- { struct task_struct * p; + struct task_struct *reaper = child_reaper; read_lock(&tasklist_lock); ! if (father->s_info != NULL){ ! pid_t initpid = father->s_info->initpid; ! if (initpid != 0 ! && father->pid != initpid){ ! struct task_struct *r = find_task_by_pid(initpid); ! if (r != NULL) reaper = r; ! } ! } for_each_task(p) { if (p->p_opptr == father) { *************** *** 166,170 **** p->exit_signal = SIGCHLD; p->self_exec_id++; ! p->p_opptr = child_reaper; if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0); } --- 174,178 ---- p->exit_signal = SIGCHLD; p->self_exec_id++; ! p->p_opptr = reaper; if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0); } diff -rc2P linux-2.4.17ctx-5/kernel/printk.c linux-2.4.17ctx-6/kernel/printk.c *** linux-2.4.17ctx-5/kernel/printk.c Sat Dec 22 22:38:45 2001 --- linux-2.4.17ctx-6/kernel/printk.c Mon Jan 21 21:46:10 2002 *************** *** 169,172 **** --- 169,174 ---- int error = 0; + if (!capable(CAP_SYS_ADMIN) && current->s_context != 0) return -EPERM; + switch (type) { case 0: /* Close log */ diff -rc2P linux-2.4.17ctx-5/kernel/signal.c linux-2.4.17ctx-6/kernel/signal.c *** linux-2.4.17ctx-5/kernel/signal.c Sun Jan 13 21:17:41 2002 --- linux-2.4.17ctx-6/kernel/signal.c Wed Jan 9 14:18:51 2002 *************** *** 593,597 **** read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pgrp == pgrp && p->s_context == current->s_context) { int err = send_sig_info(sig, info, p); if (retval) --- 593,599 ---- read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pgrp == pgrp ! && ((long)info==1 ! || p->s_context == current->s_context)) { int err = send_sig_info(sig, info, p); if (retval) *************** *** 640,645 **** p = find_task_by_pid(pid); error = -ESRCH; ! if (p && p->s_context == current->s_context) ! error = send_sig_info(sig, info, p); read_unlock(&tasklist_lock); return error; --- 642,663 ---- p = find_task_by_pid(pid); error = -ESRCH; ! if (p != NULL){ ! switch((unsigned long)info) { ! case 0: ! if(p->s_context == current->s_context){ ! error = send_sig_info(sig, info, p); ! } ! break; ! case 1: ! error = send_sig_info(sig, info, p); ! break; ! default: ! if( info->si_code == SI_KERNEL ! || p->s_context == current->s_context){ ! error = send_sig_info(sig, info, p); ! } ! break; ! } ! } read_unlock(&tasklist_lock); return error; *************** *** 1258,1261 **** --- 1276,1294 ---- #endif /* !alpha && !__ia64__ && !defined(__mips__) */ + static int set_initpid (int flags) + { + int ret = 0; + if ((flags & S_CTX_INFO_INIT)!=0){ + if (current->s_info == NULL){ + ret = -EINVAL; + }else if (current->s_info->initpid != 0){ + ret = -EPERM; + }else{ + current->s_info->initpid = current->tgid; + } + } + return ret; + } + /* Change to a new security context and reduce the capability *************** *** 1302,1305 **** --- 1335,1339 ---- sys_alloc_s_info(); if (current->s_info != NULL){ + set_initpid (flags); current->s_info->flags |= flags; } *************** *** 1307,1315 **** } }else if (ctx == -2){ ! /* We keep the same s_context, but lower the capabilities */ ! current->cap_bset &= (~remove_cap); ! ret = current->s_context; ! if (current->s_info != NULL){ ! current->s_info->flags |= flags; } }else if (ctx <= 0 || ctx > MAX_S_CONTEXT){ --- 1341,1355 ---- } }else if (ctx == -2){ ! ret = set_initpid(flags); ! if (ret == 0){ ! /* We keep the same s_context, but lower the capabilities */ ! current->cap_bset &= (~remove_cap); ! ret = current->s_context; ! if (current->s_info != NULL){ ! if ((flags & S_CTX_INFO_INIT)!=0){ ! current->s_info->initpid = current->tgid; ! } ! current->s_info->flags |= flags; ! } } }else if (ctx <= 0 || ctx > MAX_S_CONTEXT){ diff -rc2P linux-2.4.17ctx-5/kernel/sys.c linux-2.4.17ctx-6/kernel/sys.c *** linux-2.4.17ctx-5/kernel/sys.c Sun Jan 13 21:17:41 2002 --- linux-2.4.17ctx-6/kernel/sys.c Wed Jan 9 14:09:08 2002 *************** *** 1073,1076 **** --- 1073,1077 ---- atomic_set (&s_info->ticks,current->counter); s_info->flags = 0; + s_info->initpid = 0; down_read (&uts_sem); if (current->s_info != NULL){ diff -rc2P linux-2.4.17ctx-5/kernel/timer.c linux-2.4.17ctx-6/kernel/timer.c *** linux-2.4.17ctx-5/kernel/timer.c Sun Jan 13 21:17:41 2002 --- linux-2.4.17ctx-6/kernel/timer.c Sun Jan 27 14:49:24 2002 *************** *** 725,728 **** --- 725,733 ---- { /* This is SMP safe - current->pid doesn't change */ + if (current->s_info != NULL + && current->s_info->initpid == current->tgid){ + /* We are faking process 1 for this security context */ + return 1; + } return current->tgid; } *************** *** 770,773 **** --- 775,783 ---- #endif break; + } + if (current->s_info != NULL + && current->s_info->initpid == pid){ + /* We are faking process 1 for this security context */ + pid = 1; } return pid; diff -rc2P linux-2.4.17ctx-5/net/ipv4/devinet.c linux-2.4.17ctx-6/net/ipv4/devinet.c *** linux-2.4.17ctx-5/net/ipv4/devinet.c Sat Dec 22 22:38:46 2001 --- linux-2.4.17ctx-6/net/ipv4/devinet.c Thu Jan 24 12:06:09 2002 *************** *** 559,563 **** goto done; } ! switch(cmd) { case SIOCGIFADDR: /* Get interface address */ --- 559,568 ---- goto done; } ! if (ifa != NULL ! && current->ipv4root != 0 ! && current->ipv4root != ifa->ifa_local){ ! ret = -EADDRNOTAVAIL; ! goto done; ! } switch(cmd) { case SIOCGIFADDR: /* Get interface address */ *************** *** 692,695 **** --- 697,703 ---- for ( ; ifa; ifa = ifa->ifa_next) { + // We do not show other IP devices to vservers + if (current->ipv4root != 0 + && current->ipv4root != ifa->ifa_local) continue; if (!buf) { done += sizeof(ifr);