diff -rc2P linux-2.4.20/arch/i386/kernel/entry.S linux-2.4.20ctx-17/arch/i386/kernel/entry.S *** linux-2.4.20/arch/i386/kernel/entry.S 2002-12-09 10:31:24.000000000 -0500 --- linux-2.4.20ctx-17/arch/i386/kernel/entry.S 2003-03-29 21:13:24.000000000 -0500 *************** *** 658,661 **** --- 658,663 ---- .long SYMBOL_NAME(sys_ni_syscall) /* sys_free_hugepages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_exit_group */ + .long SYMBOL_NAME(sys_new_s_context) + .long SYMBOL_NAME(sys_set_ipv4root) .rept NR_syscalls-(.-sys_call_table)/4 diff -rc2P linux-2.4.20/arch/i386/kernel/ptrace.c linux-2.4.20ctx-17/arch/i386/kernel/ptrace.c *** linux-2.4.20/arch/i386/kernel/ptrace.c 2002-08-06 15:01:28.000000000 -0400 --- linux-2.4.20ctx-17/arch/i386/kernel/ptrace.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 171,175 **** get_task_struct(child); read_unlock(&tasklist_lock); ! if (!child) goto out; --- 171,175 ---- get_task_struct(child); read_unlock(&tasklist_lock); ! if (!child || child->s_context != current->s_context) goto out; diff -rc2P linux-2.4.20/arch/ppc/kernel/misc.S linux-2.4.20ctx-17/arch/ppc/kernel/misc.S *** linux-2.4.20/arch/ppc/kernel/misc.S 2002-12-09 10:31:36.000000000 -0500 --- linux-2.4.20ctx-17/arch/ppc/kernel/misc.S 2003-03-29 21:13:24.000000000 -0500 *************** *** 1185,1188 **** --- 1185,1190 ---- .long sys_ni_syscall /* 230 reserved for sys_io_submit */ .long sys_ni_syscall /* reserved for sys_io_cancel */ + .long sys_new_s_context + .long sys_set_ipv4root .rept NR_syscalls-(.-sys_call_table)/4 diff -rc2P linux-2.4.20/arch/ppc/kernel/ptrace.c linux-2.4.20ctx-17/arch/ppc/kernel/ptrace.c *** linux-2.4.20/arch/ppc/kernel/ptrace.c 2002-12-09 10:31:37.000000000 -0500 --- linux-2.4.20ctx-17/arch/ppc/kernel/ptrace.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 179,183 **** get_task_struct(child); read_unlock(&tasklist_lock); ! if (!child) goto out; --- 179,183 ---- get_task_struct(child); read_unlock(&tasklist_lock); ! if (!child || child->s_context != current->s_context) goto out; diff -rc2P linux-2.4.20/arch/sparc/kernel/systbls.S linux-2.4.20ctx-17/arch/sparc/kernel/systbls.S *** linux-2.4.20/arch/sparc/kernel/systbls.S 2002-08-06 15:01:41.000000000 -0400 --- linux-2.4.20ctx-17/arch/sparc/kernel/systbls.S 2003-03-29 21:13:24.000000000 -0500 *************** *** 71,75 **** /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep /*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl ! /*255*/ .long sys_nis_syscall, sys_nis_syscall #ifdef CONFIG_SUNOS_EMUL --- 71,77 ---- /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep /*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl ! /*255*/ .long sys_nis_syscall ! .long sys_new_s_context ! .long sys_set_ipv4root #ifdef CONFIG_SUNOS_EMUL diff -rc2P linux-2.4.20/arch/sparc64/kernel/entry.S linux-2.4.20ctx-17/arch/sparc64/kernel/entry.S *** linux-2.4.20/arch/sparc64/kernel/entry.S 2002-12-09 10:31:38.000000000 -0500 --- linux-2.4.20ctx-17/arch/sparc64/kernel/entry.S 2003-03-29 21:13:24.000000000 -0500 *************** *** 26,30 **** #define curptr g6 ! #define NR_SYSCALLS 256 /* Each OS is different... */ .text --- 26,30 ---- #define curptr g6 ! #define NR_SYSCALLS 258 /* Each OS is different... */ .text diff -rc2P linux-2.4.20/arch/sparc64/kernel/ptrace.c linux-2.4.20ctx-17/arch/sparc64/kernel/ptrace.c *** linux-2.4.20/arch/sparc64/kernel/ptrace.c 2002-12-09 10:31:38.000000000 -0500 --- linux-2.4.20ctx-17/arch/sparc64/kernel/ptrace.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 157,161 **** read_unlock(&tasklist_lock); ! if (!child) { pt_error_return(regs, ESRCH); goto out; --- 157,161 ---- read_unlock(&tasklist_lock); ! if (!child || child->s_context != current->s_context) { pt_error_return(regs, ESRCH); goto out; diff -rc2P linux-2.4.20/arch/sparc64/kernel/systbls.S linux-2.4.20ctx-17/arch/sparc64/kernel/systbls.S *** linux-2.4.20/arch/sparc64/kernel/systbls.S 2002-08-06 15:01:45.000000000 -0400 --- linux-2.4.20ctx-17/arch/sparc64/kernel/systbls.S 2003-03-29 21:13:24.000000000 -0500 *************** *** 72,75 **** --- 72,77 ---- /*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl .word sys_aplib + .word sys_new_s_context + .word sys_set_ipv4root /* Now the 64-bit native Linux syscall table. */ *************** *** 131,134 **** --- 133,138 ---- /*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl .word sys_aplib + .word sys_new_s_context + .word sys_set_ipv4root #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ *************** *** 226,229 **** --- 230,234 ---- /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sys_aplib + .word sunos_nosys, sunos_nosys #endif diff -rc2P linux-2.4.20/fs/devpts/inode.c linux-2.4.20ctx-17/fs/devpts/inode.c *** linux-2.4.20/fs/devpts/inode.c 2001-10-10 11:58:19.000000000 -0400 --- linux-2.4.20ctx-17/fs/devpts/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 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.20/fs/devpts/root.c linux-2.4.20ctx-17/fs/devpts/root.c *** linux-2.4.20/fs/devpts/root.c 2001-12-22 22:38:37.000000000 -0500 --- linux-2.4.20ctx-17/fs/devpts/root.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 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,73 ---- while ( nr - 2 < sbi->max_ptys ) { int ptynr = nr - 2; ! struct inode *inode = sbi->inodes[ptynr]; ! if ( inode != NULL ! && (current->s_context == 1 ! || 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 **** --- 105,109 ---- 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; } --- 132,147 ---- 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.20/fs/exec.c linux-2.4.20ctx-17/fs/exec.c *** linux-2.4.20/fs/exec.c 2002-12-09 10:32:03.000000000 -0500 --- linux-2.4.20ctx-17/fs/exec.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 706,710 **** int do_unlock = 0; ! new_permitted = cap_intersect(bprm->cap_permitted, cap_bset); working = cap_intersect(bprm->cap_inheritable, current->cap_inheritable); --- 706,710 ---- int do_unlock = 0; ! new_permitted = cap_intersect(bprm->cap_permitted, current->cap_bset); working = cap_intersect(bprm->cap_inheritable, current->cap_inheritable); diff -rc2P linux-2.4.20/fs/ext2/ialloc.c linux-2.4.20ctx-17/fs/ext2/ialloc.c *** linux-2.4.20/fs/ext2/ialloc.c 2002-12-09 10:32:03.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext2/ialloc.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 389,393 **** inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags & ~EXT2_BTREE_FL; if (S_ISLNK(mode)) ! inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL); inode->u.ext2_i.i_block_group = group; if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) --- 389,393 ---- inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags & ~EXT2_BTREE_FL; if (S_ISLNK(mode)) ! inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL | EXT2_APPEND_FL); inode->u.ext2_i.i_block_group = group; if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) diff -rc2P linux-2.4.20/fs/ext2/inode.c linux-2.4.20ctx-17/fs/ext2/inode.c *** linux-2.4.20/fs/ext2/inode.c 2002-12-09 10:32:03.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext2/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 47,50 **** --- 47,52 ---- } + static void ext2_truncate_nocheck (struct inode * inode); + /* * Called at the last iput() if i_nlink is zero. *************** *** 63,67 **** inode->i_size = 0; if (inode->i_blocks) ! ext2_truncate (inode); ext2_free_inode (inode); --- 65,69 ---- inode->i_size = 0; if (inode->i_blocks) ! ext2_truncate_nocheck (inode); ext2_free_inode (inode); *************** *** 787,791 **** } ! void ext2_truncate (struct inode * inode) { u32 *i_data = inode->u.ext2_i.i_data; --- 789,793 ---- } ! static void ext2_truncate_nocheck (struct inode * inode) { u32 *i_data = inode->u.ext2_i.i_data; *************** *** 802,807 **** S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; ext2_discard_prealloc(inode); --- 804,807 ---- *************** *** 877,880 **** --- 877,886 ---- } } + void ext2_truncate (struct inode * inode) + { + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) + return; + ext2_truncate_nocheck (inode); + } void ext2_read_inode (struct inode * inode) *************** *** 1006,1012 **** inode->i_flags |= S_APPEND; } ! if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) { ! inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; ! inode->i_flags |= S_IMMUTABLE; } if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) { --- 1012,1022 ---- inode->i_flags |= S_APPEND; } ! if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FILE_FL) { ! inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_FILE; ! inode->i_flags |= S_IMMUTABLE_FILE; ! } ! if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_LINK_FL) { ! inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_LINK; ! inode->i_flags |= S_IMMUTABLE_LINK; } if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) { diff -rc2P linux-2.4.20/fs/ext2/ioctl.c linux-2.4.20ctx-17/fs/ext2/ioctl.c *** linux-2.4.20/fs/ext2/ioctl.c 2002-12-09 10:32:03.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext2/ioctl.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 45,49 **** * This test looks nicer. Thanks to Pauline Middelink */ ! if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; --- 45,49 ---- * This test looks nicer. Thanks to Pauline Middelink */ ! if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; *************** *** 62,69 **** else inode->i_flags &= ~S_APPEND; ! if (flags & EXT2_IMMUTABLE_FL) ! inode->i_flags |= S_IMMUTABLE; else ! inode->i_flags &= ~S_IMMUTABLE; if (flags & EXT2_NOATIME_FL) inode->i_flags |= S_NOATIME; --- 62,76 ---- else inode->i_flags &= ~S_APPEND; ! ! if (flags & EXT2_IMMUTABLE_FILE_FL) ! inode->i_flags |= S_IMMUTABLE_FILE; ! else ! inode->i_flags &= ~S_IMMUTABLE_FILE; ! ! if (flags & EXT2_IMMUTABLE_LINK_FL) ! inode->i_flags |= S_IMMUTABLE_LINK; else ! inode->i_flags &= ~S_IMMUTABLE_LINK; ! if (flags & EXT2_NOATIME_FL) inode->i_flags |= S_NOATIME; diff -rc2P linux-2.4.20/fs/ext3/ialloc.c linux-2.4.20ctx-17/fs/ext3/ialloc.c *** linux-2.4.20/fs/ext3/ialloc.c 2002-12-09 10:32:04.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext3/ialloc.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 486,490 **** inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; if (S_ISLNK(mode)) ! inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); #ifdef EXT3_FRAGMENTS inode->u.ext3_i.i_faddr = 0; --- 486,490 ---- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; if (S_ISLNK(mode)) ! inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FILE_FL | EXT3_IMMUTABLE_LINK_FL | EXT3_APPEND_FL); #ifdef EXT3_FRAGMENTS inode->u.ext3_i.i_faddr = 0; diff -rc2P linux-2.4.20/fs/ext3/inode.c linux-2.4.20ctx-17/fs/ext3/inode.c *** linux-2.4.20/fs/ext3/inode.c 2002-12-09 10:32:04.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext3/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 158,161 **** --- 158,162 ---- } + static void ext3_truncate_nocheck (struct inode *inode); /* * Called at the last iput() if i_nlink is zero. *************** *** 187,191 **** inode->i_size = 0; if (inode->i_blocks) ! ext3_truncate(inode); /* * Kill off the orphan record which ext3_truncate created. --- 188,192 ---- inode->i_size = 0; if (inode->i_blocks) ! ext3_truncate_nocheck(inode); /* * Kill off the orphan record which ext3_truncate created. *************** *** 1840,1844 **** */ ! void ext3_truncate(struct inode * inode) { handle_t *handle; --- 1841,1845 ---- */ ! static void ext3_truncate_nocheck(struct inode * inode) { handle_t *handle; *************** *** 1856,1861 **** S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; ext3_discard_prealloc(inode); --- 1857,1860 ---- *************** *** 1987,1990 **** --- 1986,1996 ---- } + void ext3_truncate(struct inode * inode) + { + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) + return; + ext3_truncate_nocheck (inode); + } + /* * ext3_get_inode_loc returns with an extra refcount against the *************** *** 2160,2166 **** inode->i_flags |= S_APPEND; } ! if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) { /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; unused */ ! inode->i_flags |= S_IMMUTABLE; } if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) { --- 2166,2175 ---- inode->i_flags |= S_APPEND; } ! if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FILE_FL) { /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; unused */ ! inode->i_flags |= S_IMMUTABLE_FILE; ! } ! if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_LINK_FL) { ! inode->i_flags |= S_IMMUTABLE_LINK; } if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) { diff -rc2P linux-2.4.20/fs/ext3/ioctl.c linux-2.4.20ctx-17/fs/ext3/ioctl.c *** linux-2.4.20/fs/ext3/ioctl.c 2002-12-09 10:32:04.000000000 -0500 --- linux-2.4.20ctx-17/fs/ext3/ioctl.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 54,58 **** * This test looks nicer. Thanks to Pauline Middelink */ ! if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; --- 54,58 ---- * This test looks nicer. Thanks to Pauline Middelink */ ! if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FILE_FL | EXT3_IMMUTABLE_LINK_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; *************** *** 90,97 **** else inode->i_flags &= ~S_APPEND; ! if (flags & EXT3_IMMUTABLE_FL) ! inode->i_flags |= S_IMMUTABLE; else ! inode->i_flags &= ~S_IMMUTABLE; if (flags & EXT3_NOATIME_FL) inode->i_flags |= S_NOATIME; --- 90,101 ---- else inode->i_flags &= ~S_APPEND; ! if (flags & EXT3_IMMUTABLE_FILE_FL) ! inode->i_flags |= S_IMMUTABLE_FILE; else ! inode->i_flags &= ~S_IMMUTABLE_FILE; ! if (flags & EXT3_IMMUTABLE_LINK_FL) ! inode->i_flags |= S_IMMUTABLE_LINK; ! else ! inode->i_flags &= ~S_IMMUTABLE_LINK; if (flags & EXT3_NOATIME_FL) inode->i_flags |= S_NOATIME; diff -rc2P linux-2.4.20/fs/fat/file.c linux-2.4.20ctx-17/fs/fat/file.c *** linux-2.4.20/fs/fat/file.c 2001-08-12 13:56:56.000000000 -0400 --- linux-2.4.20ctx-17/fs/fat/file.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 120,124 **** if (IS_RDONLY (inode)) return /* -EPERM */; ! if (IS_IMMUTABLE(inode)) return /* -EPERM */; cluster = 1 << sbi->cluster_bits; --- 120,124 ---- if (IS_RDONLY (inode)) return /* -EPERM */; ! if (IS_IMMUTABLE_FILE(inode)) return /* -EPERM */; cluster = 1 << sbi->cluster_bits; diff -rc2P linux-2.4.20/fs/fat/inode.c linux-2.4.20ctx-17/fs/fat/inode.c *** linux-2.4.20/fs/fat/inode.c 2002-08-06 15:02:23.000000000 -0400 --- linux-2.4.20ctx-17/fs/fat/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 950,954 **** if(de->attr & ATTR_SYS) if (sbi->options.sys_immutable) ! inode->i_flags |= S_IMMUTABLE; MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ --- 950,954 ---- if(de->attr & ATTR_SYS) if (sbi->options.sys_immutable) ! inode->i_flags |= S_IMMUTABLE_FILE; MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ diff -rc2P linux-2.4.20/fs/hpfs/file.c linux-2.4.20ctx-17/fs/hpfs/file.c *** linux-2.4.20/fs/hpfs/file.c 2001-08-12 20:37:53.000000000 -0400 --- linux-2.4.20ctx-17/fs/hpfs/file.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 61,65 **** void hpfs_truncate(struct inode *i) { ! if (IS_IMMUTABLE(i)) return /*-EPERM*/; i->i_hpfs_n_secs = 0; i->i_blocks = 1 + ((i->i_size + 511) >> 9); --- 61,65 ---- void hpfs_truncate(struct inode *i) { ! if (IS_IMMUTABLE_FILE(i)) return /*-EPERM*/; i->i_hpfs_n_secs = 0; i->i_blocks = 1 + ((i->i_size + 511) >> 9); diff -rc2P linux-2.4.20/fs/intermezzo/vfs.c linux-2.4.20ctx-17/fs/intermezzo/vfs.c *** linux-2.4.20/fs/intermezzo/vfs.c 2002-12-09 10:32:04.000000000 -0500 --- linux-2.4.20ctx-17/fs/intermezzo/vfs.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 141,145 **** return -EPERM; if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| ! IS_IMMUTABLE(victim->d_inode)) return -EPERM; if (isdir) { --- 141,145 ---- return -EPERM; if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| ! IS_IMMUTABLE_LINK(victim->d_inode)) return -EPERM; if (isdir) { *************** *** 263,267 **** } ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; --- 263,267 ---- } ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; *************** *** 378,382 **** } ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; --- 378,382 ---- } ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; *************** *** 773,777 **** */ error = -EPERM; ! if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { EXIT; goto exit_lock; --- 773,777 ---- */ error = -EPERM; ! if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode)) { EXIT; goto exit_lock; *************** *** 2363,2367 **** } ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; --- 2363,2367 ---- } ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; diff -rc2P linux-2.4.20/fs/namei.c linux-2.4.20ctx-17/fs/namei.c *** linux-2.4.20/fs/namei.c 2002-12-09 10:32:05.000000000 -0500 --- linux-2.4.20ctx-17/fs/namei.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 153,156 **** --- 153,165 ---- 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 + && S_ISDIR(mode) + && current->s_context != 0) return -EACCES; if (mask & MAY_WRITE) { /* *************** *** 164,168 **** * Nobody gets write access to an immutable file. */ ! if (IS_IMMUTABLE(inode)) return -EACCES; } --- 173,177 ---- * Nobody gets write access to an immutable file. */ ! if (IS_IMMUTABLE_FILE(inode)) return -EACCES; } *************** *** 903,908 **** if (IS_APPEND(dir)) return -EPERM; ! if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| ! IS_IMMUTABLE(victim->d_inode)) return -EPERM; if (isdir) { --- 912,916 ---- if (IS_APPEND(dir)) return -EPERM; ! if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||IS_IMMUTABLE_LINK(victim->d_inode)) return -EPERM; if (isdir) { *************** *** 1617,1621 **** */ error = -EPERM; ! if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto exit_lock; if (!dir->i_op || !dir->i_op->link) --- 1625,1629 ---- */ error = -EPERM; ! if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode)) goto exit_lock; if (!dir->i_op || !dir->i_op->link) diff -rc2P linux-2.4.20/fs/nfsd/vfs.c linux-2.4.20ctx-17/fs/nfsd/vfs.c *** linux-2.4.20/fs/nfsd/vfs.c 2002-12-09 10:32:05.000000000 -0500 --- linux-2.4.20ctx-17/fs/nfsd/vfs.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 1477,1481 **** return 0; #if 0 ! dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", acc, (acc & MAY_READ)? " read" : "", --- 1477,1481 ---- return 0; #if 0 ! dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s%s\n", acc, (acc & MAY_READ)? " read" : "", *************** *** 1487,1491 **** (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "", inode->i_mode, ! IS_IMMUTABLE(inode)? " immut" : "", IS_APPEND(inode)? " append" : "", IS_RDONLY(inode)? " ro" : ""); --- 1487,1492 ---- (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "", inode->i_mode, ! IS_IMMUTABLE_FILE(inode)? " immut(F)" : "", ! IS_IMMUTABLE_LINK(inode)? " immut(L)" : "", IS_APPEND(inode)? " append" : "", IS_RDONLY(inode)? " ro" : ""); *************** *** 1506,1510 **** if (EX_RDONLY(exp) || IS_RDONLY(inode)) return nfserr_rofs; ! if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) return nfserr_perm; } --- 1507,1511 ---- if (EX_RDONLY(exp) || IS_RDONLY(inode)) return nfserr_rofs; ! if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE_FILE(inode)) return nfserr_perm; } diff -rc2P linux-2.4.20/fs/open.c linux-2.4.20ctx-17/fs/open.c *** linux-2.4.20/fs/open.c 2002-12-09 10:32:05.000000000 -0500 --- linux-2.4.20ctx-17/fs/open.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 147,151 **** error = -EPERM; ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto dput_and_out; --- 147,151 ---- error = -EPERM; ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto dput_and_out; *************** *** 479,483 **** goto out_putf; err = -EPERM; ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_putf; if (mode == (mode_t) -1) --- 479,483 ---- goto out_putf; err = -EPERM; ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto out_putf; if (mode == (mode_t) -1) *************** *** 510,514 **** error = -EPERM; ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto dput_and_out; --- 510,514 ---- error = -EPERM; ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto dput_and_out; *************** *** 540,544 **** goto out; error = -EPERM; ! if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; if (user == (uid_t) -1) --- 540,544 ---- goto out; error = -EPERM; ! if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto out; if (user == (uid_t) -1) diff -rc2P linux-2.4.20/fs/proc/array.c linux-2.4.20ctx-17/fs/proc/array.c *** linux-2.4.20/fs/proc/array.c 2002-08-06 15:02:24.000000000 -0400 --- linux-2.4.20ctx-17/fs/proc/array.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 76,79 **** --- 76,80 ---- #include #include + #include /* Gcc optimizes away "strlen(x)" for constant x */ *************** *** 148,153 **** { int g; ! read_lock(&tasklist_lock); buffer += sprintf(buffer, "State:\t%s\n" --- 149,158 ---- { int g; ! pid_t ppid; read_lock(&tasklist_lock); + ppid = p->p_opptr->pid; + if (ppid != 0 + && 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); --- 164,168 ---- "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); *************** *** 267,274 **** return buffer + sprintf(buffer, "CapInh:\t%016x\n" "CapPrm:\t%016x\n" ! "CapEff:\t%016x\n", cap_t(p->cap_inheritable), cap_t(p->cap_permitted), ! cap_t(p->cap_effective)); } --- 272,281 ---- return buffer + sprintf(buffer, "CapInh:\t%016x\n" "CapPrm:\t%016x\n" ! "CapEff:\t%016x\n" ! "CapBset:\t%016x\n", cap_t(p->cap_inheritable), cap_t(p->cap_permitted), ! cap_t(p->cap_effective), ! cap_t(p->cap_bset)); } *************** *** 292,295 **** --- 299,345 ---- buffer = task_sig(task, buffer); buffer = task_cap(task, buffer); + #ifdef __NR_new_s_context + if (task->s_info != NULL){ + int i; + buffer += sprintf (buffer,"s_context: %d [",task->s_context); + for (i=0; is_info->s_context[i]; + if (ctx == 0) break; + buffer += sprintf (buffer," %d",ctx); + } + *buffer++ = ']'; + *buffer++ = '\n'; + buffer += sprintf (buffer,"ctxticks: %d %ld %d\n" + ,atomic_read(&task->s_info->ticks),task->counter + ,task->s_info->refcount); + buffer += sprintf (buffer,"ctxflags: %d\n" + ,task->s_info->flags); + buffer += sprintf (buffer,"initpid: %d\n" + ,task->s_info->initpid); + }else{ + buffer += sprintf (buffer,"s_context: %d\n",task->s_context); + buffer += sprintf (buffer,"ctxticks: none\n"); + buffer += sprintf (buffer,"ctxflags: none\n"); + buffer += sprintf (buffer,"initpid: none\n"); + } + if (task->ip_info != NULL){ + int i; + buffer += sprintf (buffer,"ipv4root:"); + for (i=0; iip_info->nbipv4; i++){ + buffer += sprintf (buffer," %08x" + ,task->ip_info->ipv4[i]); + } + *buffer++ = '\n'; + buffer += sprintf (buffer,"ipv4root_bcast: %08x\n" + ,task->ip_info->v4_bcast); + buffer += sprintf (buffer,"ipv4root_refcnt: %d\n" + ,task->ip_info->refcount); + }else{ + buffer += sprintf (buffer,"ipv4root: 0\n"); + buffer += sprintf (buffer,"ipv4root_bcast: 0\n"); + } + buffer += sprintf (buffer,"__NR_new_s_context: %d\n",__NR_new_s_context); + buffer += sprintf (buffer,"__NR_set_ipv4root: %d rev2\n",__NR_set_ipv4root); + #endif #if defined(CONFIG_ARCH_S390) buffer = task_show_regs(task, buffer); *************** *** 345,348 **** --- 395,400 ---- 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.20/fs/proc/base.c linux-2.4.20ctx-17/fs/proc/base.c *** linux-2.4.20/fs/proc/base.c 2002-08-06 15:02:24.000000000 -0400 --- linux-2.4.20ctx-17/fs/proc/base.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 1020,1023 **** --- 1020,1029 ---- goto out; + if (pid != 1 + && current->s_context != 1 + && task->s_context != current->s_context){ + free_task_struct(task); + goto out; + } inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO); *************** *** 1030,1034 **** inode->i_fop = &proc_base_operations; inode->i_nlink = 3; ! inode->i_flags|=S_IMMUTABLE; dentry->d_op = &pid_base_dentry_operations; --- 1036,1040 ---- inode->i_fop = &proc_base_operations; inode->i_nlink = 3; ! inode->i_flags|=S_IMMUTABLE_FILE; dentry->d_op = &pid_base_dentry_operations; *************** *** 1066,1069 **** --- 1072,1088 ---- if (!pid) continue; + /* Even if the pid 1 is not part of the security context */ + /* we show it anyway. This makes the security box */ + /* more standard (and helps pstree do its job) */ + /* So current process "knows" pid 1 exist anyway and can't */ + /* send any signal either */ + + /* A process with security context 1 can see all processes */ + if (pid != 1 + && 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.20/fs/reiserfs/inode.c linux-2.4.20ctx-17/fs/reiserfs/inode.c *** linux-2.4.20/fs/reiserfs/inode.c 2002-12-09 10:32:05.000000000 -0500 --- linux-2.4.20ctx-17/fs/reiserfs/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 1549,1553 **** /* symlink cannot be immutable or append only, right? */ if( S_ISLNK( inode -> i_mode ) ) ! inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND ); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; --- 1549,1553 ---- /* symlink cannot be immutable or append only, right? */ if( S_ISLNK( inode -> i_mode ) ) ! inode -> i_flags &= ~ ( S_IMMUTABLE_FILE | S_APPEND ); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; *************** *** 2083,2090 **** else inode -> i_flags &= ~S_SYNC; ! if( sd_attrs & REISERFS_IMMUTABLE_FL ) ! inode -> i_flags |= S_IMMUTABLE; else ! inode -> i_flags &= ~S_IMMUTABLE; if( sd_attrs & REISERFS_NOATIME_FL ) inode -> i_flags |= S_NOATIME; --- 2083,2094 ---- else inode -> i_flags &= ~S_SYNC; ! if( sd_attrs & REISERFS_IMMUTABLE_FILE_FL ) ! inode -> i_flags |= S_IMMUTABLE_FILE; else ! inode -> i_flags &= ~S_IMMUTABLE_FILE; ! if( sd_attrs & REISERFS_IMMUTABLE_LINK_FL ) ! inode -> i_flags |= S_IMMUTABLE_LINK; ! else ! inode -> i_flags &= ~S_IMMUTABLE_LINK; if( sd_attrs & REISERFS_NOATIME_FL ) inode -> i_flags |= S_NOATIME; *************** *** 2101,2108 **** { if( reiserfs_attrs( inode -> i_sb ) ) { ! if( inode -> i_flags & S_IMMUTABLE ) ! *sd_attrs |= REISERFS_IMMUTABLE_FL; else ! *sd_attrs &= ~REISERFS_IMMUTABLE_FL; if( inode -> i_flags & S_SYNC ) *sd_attrs |= REISERFS_SYNC_FL; --- 2105,2116 ---- { if( reiserfs_attrs( inode -> i_sb ) ) { ! if( inode -> i_flags & S_IMMUTABLE_FILE ) ! *sd_attrs |= REISERFS_IMMUTABLE_FILE_FL; ! else ! *sd_attrs &= ~REISERFS_IMMUTABLE_FILE_FL; ! if( inode -> i_flags & S_IMMUTABLE_LINK ) ! *sd_attrs |= REISERFS_IMMUTABLE_LINK_FL; else ! *sd_attrs &= ~REISERFS_IMMUTABLE_LINK_FL; if( inode -> i_flags & S_SYNC ) *sd_attrs |= REISERFS_SYNC_FL; diff -rc2P linux-2.4.20/fs/reiserfs/ioctl.c linux-2.4.20ctx-17/fs/reiserfs/ioctl.c *** linux-2.4.20/fs/reiserfs/ioctl.c 2002-12-09 10:32:05.000000000 -0500 --- linux-2.4.20ctx-17/fs/reiserfs/ioctl.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 52,56 **** return -EFAULT; ! if ( ( flags & REISERFS_IMMUTABLE_FL ) && !capable( CAP_LINUX_IMMUTABLE ) ) return -EPERM; --- 52,56 ---- return -EFAULT; ! if ( ( flags & (REISERFS_IMMUTABLE_FILE_FL | REISERFS_IMMUTABLE_LINK_FL) ) && !capable( CAP_LINUX_IMMUTABLE ) ) return -EPERM; diff -rc2P linux-2.4.20/fs/udf/inode.c linux-2.4.20ctx-17/fs/udf/inode.c *** linux-2.4.20/fs/udf/inode.c 2002-08-06 15:02:25.000000000 -0400 --- linux-2.4.20ctx-17/fs/udf/inode.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 861,865 **** S_ISLNK(inode->i_mode))) return; ! if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; --- 861,865 ---- S_ISLNK(inode->i_mode))) return; ! if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; diff -rc2P linux-2.4.20/fs/ufs/truncate.c linux-2.4.20ctx-17/fs/ufs/truncate.c *** linux-2.4.20/fs/ufs/truncate.c 2002-12-09 10:32:09.000000000 -0500 --- linux-2.4.20ctx-17/fs/ufs/truncate.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 435,439 **** if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; ! if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; while (1) { --- 435,439 ---- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; ! if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; while (1) { diff -rc2P linux-2.4.20/include/asm-i386/unistd.h linux-2.4.20ctx-17/include/asm-i386/unistd.h *** linux-2.4.20/include/asm-i386/unistd.h 2002-12-09 10:32:10.000000000 -0500 --- linux-2.4.20ctx-17/include/asm-i386/unistd.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 258,261 **** --- 258,263 ---- #define __NR_free_hugepages 251 #define __NR_exit_group 252 + #define __NR_new_s_context 253 + #define __NR_set_ipv4root 254 /* user-visible error numbers are in the range -1 - -124: see */ diff -rc2P linux-2.4.20/include/asm-ppc/unistd.h linux-2.4.20ctx-17/include/asm-ppc/unistd.h *** linux-2.4.20/include/asm-ppc/unistd.h 2002-12-09 10:32:21.000000000 -0500 --- linux-2.4.20ctx-17/include/asm-ppc/unistd.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 242,245 **** --- 242,247 ---- #define __NR_io_cancel 231 #endif + #define __NR_new_s_context 232 + #define __NR_set_ipv4root 233 #define __NR(n) #n diff -rc2P linux-2.4.20/include/asm-sparc/unistd.h linux-2.4.20ctx-17/include/asm-sparc/unistd.h *** linux-2.4.20/include/asm-sparc/unistd.h 2002-08-06 15:02:39.000000000 -0400 --- linux-2.4.20ctx-17/include/asm-sparc/unistd.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 272,275 **** --- 272,277 ---- #define __NR_nfsservctl 254 #define __NR_aplib 255 + #define __NR_new_s_context 256 + #define __NR_set_ipv4root 257 #define _syscall0(type,name) \ diff -rc2P linux-2.4.20/include/asm-sparc64/unistd.h linux-2.4.20ctx-17/include/asm-sparc64/unistd.h *** linux-2.4.20/include/asm-sparc64/unistd.h 2002-08-06 15:02:40.000000000 -0400 --- linux-2.4.20ctx-17/include/asm-sparc64/unistd.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 274,277 **** --- 274,279 ---- #define __NR_nfsservctl 254 #define __NR_aplib 255 + #define __NR_new_s_context 256 + #define __NR_set_ipv4root 257 #define _syscall0(type,name) \ diff -rc2P linux-2.4.20/include/linux/capability.h linux-2.4.20ctx-17/include/linux/capability.h *** linux-2.4.20/include/linux/capability.h 2001-11-23 15:07:52.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/capability.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 232,235 **** --- 232,236 ---- arbitrary SCSI commands */ /* Allow setting encryption key on loopback filesystem */ + /* Allow the selection of a security context */ #define CAP_SYS_ADMIN 21 *************** *** 280,283 **** --- 281,288 ---- #define CAP_LEASE 28 + /* Allow opening special device file */ + + #define CAP_OPENDEV 29 + #ifdef __KERNEL__ /* diff -rc2P linux-2.4.20/include/linux/devpts_fs_info.h linux-2.4.20ctx-17/include/linux/devpts_fs_info.h *** linux-2.4.20/include/linux/devpts_fs_info.h 1969-12-31 19:00:00.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/devpts_fs_info.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 0 **** --- 1,4 ---- + struct devpts_inode_info{ + int s_context; + }; + diff -rc2P linux-2.4.20/include/linux/ext2_fs.h linux-2.4.20ctx-17/include/linux/ext2_fs.h *** linux-2.4.20/include/linux/ext2_fs.h 2001-10-31 15:32:45.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/ext2_fs.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 188,192 **** #define EXT2_COMPR_FL 0x00000004 /* Compress file */ #define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ ! #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ --- 188,192 ---- #define EXT2_COMPR_FL 0x00000004 /* Compress file */ #define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ ! #define EXT2_IMMUTABLE_FILE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ *************** *** 199,206 **** /* End compression flags --- maybe not all used */ #define EXT2_BTREE_FL 0x00001000 /* btree format dir */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ ! #define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */ ! #define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ /* --- 199,207 ---- /* End compression flags --- maybe not all used */ #define EXT2_BTREE_FL 0x00001000 /* btree format dir */ + #define EXT2_IMMUTABLE_LINK_FL 0x00008000 /* Immutable link */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ ! #define EXT2_FL_USER_VISIBLE 0x00009FFF /* User visible flags */ ! #define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ /* diff -rc2P linux-2.4.20/include/linux/ext3_fs.h linux-2.4.20ctx-17/include/linux/ext3_fs.h *** linux-2.4.20/include/linux/ext3_fs.h 2002-12-09 10:32:22.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/ext3_fs.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 191,195 **** #define EXT3_COMPR_FL 0x00000004 /* Compress file */ #define EXT3_SYNC_FL 0x00000008 /* Synchronous updates */ ! #define EXT3_IMMUTABLE_FL 0x00000010 /* Immutable file */ #define EXT3_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT3_NODUMP_FL 0x00000040 /* do not dump file */ --- 191,195 ---- #define EXT3_COMPR_FL 0x00000004 /* Compress file */ #define EXT3_SYNC_FL 0x00000008 /* Synchronous updates */ ! #define EXT3_IMMUTABLE_FILE_FL 0x00000010 /* Immutable file */ #define EXT3_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT3_NODUMP_FL 0x00000040 /* do not dump file */ *************** *** 204,211 **** #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ ! #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ ! #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ /* --- 204,212 ---- #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ + #define EXT3_IMMUTABLE_LINK_FL 0x00008000 /* Immutable link */ #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ ! #define EXT3_FL_USER_VISIBLE 0x0000DFFF /* User visible flags */ ! #define EXT3_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ /* diff -rc2P linux-2.4.20/include/linux/fs.h linux-2.4.20ctx-17/include/linux/fs.h *** linux-2.4.20/include/linux/fs.h 2002-12-09 10:32:22.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/fs.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 129,139 **** /* Inode flags - they have nothing to superblock flags now */ ! #define S_SYNC 1 /* Writes are synced at once */ ! #define S_NOATIME 2 /* Do not update access times */ ! #define S_QUOTA 4 /* Quota initialized for file */ ! #define S_APPEND 8 /* Append-only file */ ! #define S_IMMUTABLE 16 /* Immutable file */ ! #define S_DEAD 32 /* removed, but still open directory */ ! #define S_NOQUOTA 64 /* Inode is not counted to quota */ /* --- 129,140 ---- /* Inode flags - they have nothing to superblock flags now */ ! #define S_SYNC 1 /* Writes are synced at once */ ! #define S_NOATIME 2 /* Do not update access times */ ! #define S_QUOTA 4 /* Quota initialized for file */ ! #define S_APPEND 8 /* Append-only file */ ! #define S_IMMUTABLE_FILE 16 /* Immutable file */ ! #define S_DEAD 32 /* removed, but still open directory */ ! #define S_NOQUOTA 64 /* Inode is not counted to quota */ ! #define S_IMMUTABLE_LINK 128 /* Immutable links */ /* *************** *** 159,163 **** #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) ! #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME)) #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME) --- 160,165 ---- #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) ! #define IS_IMMUTABLE_FILE(inode) ((inode)->i_flags & S_IMMUTABLE_FILE) ! #define IS_IMMUTABLE_LINK(inode) ((((inode)->i_flags & S_IMMUTABLE_FILE) << 3) ^ ((inode)->i_flags & S_IMMUTABLE_LINK) ) #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME)) #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME) *************** *** 321,324 **** --- 323,327 ---- #include #include + #include /* *************** *** 362,370 **** * This is the inode attributes flag definitions */ ! #define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */ ! #define ATTR_FLAG_NOATIME 2 /* Don't update atime */ ! #define ATTR_FLAG_APPEND 4 /* Append-only file */ ! #define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */ ! #define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */ /* --- 365,374 ---- * This is the inode attributes flag definitions */ ! #define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */ ! #define ATTR_FLAG_NOATIME 2 /* Don't update atime */ ! #define ATTR_FLAG_APPEND 4 /* Append-only file */ ! #define ATTR_FLAG_IMMUTABLE_FILE 8 /* Immutable file */ ! #define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */ ! #define ATTR_FLAG_IMMUTABLE_LINK 32 /* Immutable file */ /* *************** *** 511,514 **** --- 515,519 ---- 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.20/include/linux/reiserfs_fs.h linux-2.4.20ctx-17/include/linux/reiserfs_fs.h *** linux-2.4.20/include/linux/reiserfs_fs.h 2002-12-09 10:32:23.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/reiserfs_fs.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 737,741 **** /* we want common flags to have the same values as in ext2, so chattr(1) will work without problems */ ! #define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL #define REISERFS_SYNC_FL EXT2_SYNC_FL #define REISERFS_NOATIME_FL EXT2_NOATIME_FL --- 737,742 ---- /* we want common flags to have the same values as in ext2, so chattr(1) will work without problems */ ! #define REISERFS_IMMUTABLE_FILE_FL EXT2_IMMUTABLE_FILE_FL ! #define REISERFS_IMMUTABLE_LINK_FL EXT2_IMMUTABLE_LINK_FL #define REISERFS_SYNC_FL EXT2_SYNC_FL #define REISERFS_NOATIME_FL EXT2_NOATIME_FL *************** *** 753,757 **** /* persistent flags that file inherits from the parent directory */ ! #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \ REISERFS_SYNC_FL | \ REISERFS_NOATIME_FL | \ --- 754,759 ---- /* persistent flags that file inherits from the parent directory */ ! #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FILE_FL | \ ! REISERFS_IMMUTABLE_LINK_FL | \ REISERFS_SYNC_FL | \ REISERFS_NOATIME_FL | \ diff -rc2P linux-2.4.20/include/linux/sched.h linux-2.4.20ctx-17/include/linux/sched.h *** linux-2.4.20/include/linux/sched.h 2002-12-09 10:32:23.000000000 -0500 --- linux-2.4.20ctx-17/include/linux/sched.h 2003-03-29 21:15:39.000000000 -0500 *************** *** 275,278 **** --- 275,279 ---- struct user_struct *next, **pprev; uid_t uid; + int s_context; }; *************** *** 282,285 **** --- 283,340 ---- __user; }) + + /* + We may have a different domainname and nodename for each security + context. By default, a security context share the same as its + parent, potentially the information in system_utsname + */ + #define S_CTX_INFO_LOCK 1 /* Can't request a new s_context */ + #define S_CTX_INFO_SCHED 2 /* All process in the s_context */ + /* Contribute to the schedular */ + #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 */ + #define S_CTX_INFO_HIDEINFO 32 /* Hide some information in /proc */ + #define S_CTX_INFO_ULIMIT 64 /* Use ulimit of the current process */ + /* to become the global limits */ + /* of the context */ + + #define NB_IPV4ROOT 16 + #define NB_S_CONTEXT 16 + + struct context_info{ + int refcount; + short int s_context[NB_S_CONTEXT];/* root is allowed to switch the current */ + /* security context using any in this table */ + unsigned long rlim[RLIM_NLIMITS]; /* Per context limit */ + atomic_t res[RLIM_NLIMITS]; /* Current value */ + char nodename[65]; + char domainname[65]; + int flags; /* S_CTX_INFO_xxx */ + 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 */ + void *data1; + void *data2; + void *data3; + void *data4; + }; + + struct iproot_info{ + unsigned long mark; /* Special signature for debugging */ + atomic_t refcount; + int nbipv4; + __u32 ipv4[NB_IPV4ROOT];/* Process can only bind to these IPs */ + /* The first one is used to connect */ + /* and for bind any service */ + /* The other must be used explicity when */ + /* binding */ + __u32 v4_bcast; /* Broadcast address used to receive UDP packets */ + }; + + extern struct user_struct root_user; #define INIT_USER (&root_user) *************** *** 408,411 **** --- 463,472 ---- size_t sas_ss_size; int (*notifier)(void *priv); + /* Field to make virtual server running in chroot more isolated */ + int s_context; /* Process can only deal with other processes */ + /* with the same s_context */ + __u32 cap_bset; /* Maximum capability of this process and children */ + struct context_info *s_info; + struct iproot_info *ip_info; void *notifier_data; sigset_t *notifier_mask; *************** *** 511,514 **** --- 572,576 ---- alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + cap_bset: CAP_INIT_EFF_SET, \ } *************** *** 575,579 **** /* per-UID process charging. */ ! extern struct user_struct * alloc_uid(uid_t); extern void free_uid(struct user_struct *); --- 637,641 ---- /* per-UID process charging. */ ! extern struct user_struct * alloc_uid(int, uid_t); extern void free_uid(struct user_struct *); *************** *** 944,947 **** --- 1006,1017 ---- } + /* Manage the reference count of the context_info pointer */ + void sys_release_s_info (struct task_struct *); + void sys_assign_s_info (struct task_struct *); + void sys_alloc_s_info (void); + void sys_release_ip_info (struct iproot_info *); + void sys_assign_ip_info (struct iproot_info *); + void sys_alloc_ip_info (void); + static inline int need_resched(void) { diff -rc2P linux-2.4.20/include/net/route.h linux-2.4.20ctx-17/include/net/route.h *** linux-2.4.20/include/net/route.h 2002-08-06 15:02:44.000000000 -0400 --- linux-2.4.20ctx-17/include/net/route.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 165,168 **** --- 165,188 ---- { int err; + struct iproot_info *ip_info = current->ip_info; + if (ip_info != NULL){ + __u32 ipv4root = ip_info->ipv4[0]; + if (ipv4root != 0){ + if (src == 0){ + src = dst == 0x0100007f + ? 0x0100007f: ipv4root; + }else{ + int n=ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == src) break; + } + if (i==n) return -EPERM; + } + if (dst == 0x0100007f && current->s_context != 0){ + dst = ipv4root; + } + } + } err = ip_route_output(rp, dst, src, tos, oif); if (err || (dst && src)) diff -rc2P linux-2.4.20/include/net/sock.h linux-2.4.20ctx-17/include/net/sock.h *** linux-2.4.20/include/net/sock.h 2002-08-06 15:02:44.000000000 -0400 --- linux-2.4.20ctx-17/include/net/sock.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 488,491 **** --- 488,492 ---- struct sock { + /* See tcp.h comment on tcp_tw_bucket */ /* Socket demultiplex comparisons on incoming packets. */ __u32 daddr; /* Foreign IPv4 addr */ *************** *** 509,512 **** --- 510,515 ---- unsigned char shutdown; atomic_t refcnt; /* Reference count */ + struct iproot_info *ip_info; + /* End of common section with tcp_tw_bucket */ socket_lock_t lock; /* Synchronizer... */ *************** *** 526,529 **** --- 529,533 ---- unsigned int allocation; /* Allocation mode */ int sndbuf; /* Size of send buffer in bytes */ + __u32 rcv_saddr2; /* Second bound ipv4 addr, for ipv4root */ struct sock *prev; *************** *** 669,673 **** /* RPC layer private data */ void *user_data; ! /* Callbacks */ void (*state_change)(struct sock *sk); --- 673,680 ---- /* RPC layer private data */ void *user_data; ! ! /* Context of process creating this socket */ ! int s_context; ! /* Callbacks */ void (*state_change)(struct sock *sk); diff -rc2P linux-2.4.20/include/net/tcp.h linux-2.4.20ctx-17/include/net/tcp.h *** linux-2.4.20/include/net/tcp.h 2002-12-09 10:32:24.000000000 -0500 --- linux-2.4.20ctx-17/include/net/tcp.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 173,176 **** --- 173,177 ---- rcv_wscale; /* It is also TW bucket specific */ atomic_t refcnt; + struct ipv4_info *ip_info; /* And these are ours. */ *************** *** 191,194 **** --- 192,196 ---- struct in6_addr v6_rcv_saddr; #endif + int s_context; }; diff -rc2P linux-2.4.20/ipc/util.c linux-2.4.20ctx-17/ipc/util.c *** linux-2.4.20/ipc/util.c 2002-12-09 10:32:24.000000000 -0500 --- linux-2.4.20ctx-17/ipc/util.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 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.20/ipc/util.h linux-2.4.20ctx-17/ipc/util.h *** linux-2.4.20/ipc/util.h 2002-12-09 10:32:24.000000000 -0500 --- linux-2.4.20ctx-17/ipc/util.h 2003-03-29 21:13:24.000000000 -0500 *************** *** 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.20/kernel/exit.c linux-2.4.20ctx-17/kernel/exit.c *** linux-2.4.20/kernel/exit.c 2002-12-09 10:32:26.000000000 -0500 --- linux-2.4.20ctx-17/kernel/exit.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 67,70 **** --- 67,72 ---- if (current->counter >= MAX_COUNTER) current->counter = MAX_COUNTER; + sys_release_s_info(p); + sys_release_ip_info(p->ip_info); p->pid = 0; free_task_struct(p); *************** *** 160,165 **** --- 162,176 ---- { struct task_struct * p; + struct task_struct *vchild_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) vchild_reaper = r; + } + } for_each_task(p) { *************** *** 170,174 **** /* Make sure we're not reparenting to ourselves */ ! p->p_opptr = child_reaper; if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0); --- 181,185 ---- /* Make sure we're not reparenting to ourselves */ ! p->p_opptr = vchild_reaper; if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0); diff -rc2P linux-2.4.20/kernel/fork.c linux-2.4.20ctx-17/kernel/fork.c *** linux-2.4.20/kernel/fork.c 2002-12-09 10:32:26.000000000 -0500 --- linux-2.4.20ctx-17/kernel/fork.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 604,607 **** --- 604,611 ---- retval = -EAGAIN; + if (p->s_info != NULL && (p->s_info->flags & S_CTX_INFO_NPROC)!=0){ + if (p->s_info->refcount >= p->rlim[RLIMIT_NPROC].rlim_max) + goto bad_fork_free; + } /* * Check if we are over our maximum process limit, but be sure to *************** *** 614,617 **** --- 618,624 ---- goto bad_fork_free; + sys_assign_s_info (p); + sys_assign_ip_info (p->ip_info); + atomic_inc(&p->user->__count); atomic_inc(&p->user->processes); diff -rc2P linux-2.4.20/kernel/printk.c linux-2.4.20ctx-17/kernel/printk.c *** linux-2.4.20/kernel/printk.c 2002-08-06 15:02:44.000000000 -0400 --- linux-2.4.20ctx-17/kernel/printk.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 173,176 **** --- 173,178 ---- 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.20/kernel/sched.c linux-2.4.20ctx-17/kernel/sched.c *** linux-2.4.20/kernel/sched.c 2002-12-09 10:32:26.000000000 -0500 --- linux-2.4.20ctx-17/kernel/sched.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 166,170 **** * over.. */ ! weight = p->counter; if (!weight) goto out; --- 166,176 ---- * over.. */ ! if (p->s_info != NULL ! && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ ! weight = atomic_read (&p->s_info->ticks)/p->s_info->refcount; ! weight = (weight+p->counter)>>1; ! }else{ ! weight = p->counter; ! } if (!weight) goto out; *************** *** 619,624 **** spin_unlock_irq(&runqueue_lock); read_lock(&tasklist_lock); ! for_each_task(p) p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); --- 625,645 ---- spin_unlock_irq(&runqueue_lock); read_lock(&tasklist_lock); ! /* ! Reset the s_info->ticks to the sum off all ! member processes p->counter ! */ ! for_each_task(p){ ! if (p->s_info != NULL ! && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ ! atomic_set (&p->s_info->ticks,0); ! } ! } ! for_each_task(p){ p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + atomic_add (p->counter,&p->s_info->ticks); + } + } read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); diff -rc2P linux-2.4.20/kernel/signal.c linux-2.4.20ctx-17/kernel/signal.c *** linux-2.4.20/kernel/signal.c 2002-12-09 10:32:26.000000000 -0500 --- linux-2.4.20ctx-17/kernel/signal.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 597,601 **** read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pgrp == pgrp && thread_group_leader(p)) { int err = send_sig_info(sig, info, p); if (retval) --- 597,603 ---- read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pgrp == pgrp && thread_group_leader(p) ! && ((long)info==1 ! || p->s_context == current->s_context)) { int err = send_sig_info(sig, info, p); if (retval) *************** *** 651,655 **** p = tg; } ! error = send_sig_info(sig, info, p); } read_unlock(&tasklist_lock); --- 653,672 ---- p = tg; } ! 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); *************** *** 675,679 **** read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pid > 1 && p != current && thread_group_leader(p)) { int err = send_sig_info(sig, info, p); ++count; --- 692,697 ---- read_lock(&tasklist_lock); for_each_task(p) { ! if (p->pid > 1 && p != current && thread_group_leader(p) ! && p->s_context == current->s_context) { int err = send_sig_info(sig, info, p); ++count; *************** *** 1299,1300 **** --- 1317,1462 ---- } #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; + } + + static inline int switch_user_struct(int new_context) + { + struct user_struct *new_user; + + new_user = alloc_uid(new_context, current->uid); + if (!new_user) + return -ENOMEM; + + if (new_user != current->user) { + struct user_struct *old_user = current->user; + + atomic_inc(&new_user->processes); + atomic_dec(&old_user->processes); + current->user = new_user; + free_uid(old_user); + } + return 0; + } + + /* + Change to a new security context and reduce the capability + basic set of the current process + */ + asmlinkage int + sys_new_s_context(int ctx, __u32 remove_cap, int flags) + { + #define MAX_S_CONTEXT 65535 /* Arbitrary limit */ + int ret = -EPERM; + if (ctx == -1){ + if (current->s_info == NULL + || (current->s_info->flags & S_CTX_INFO_LOCK) == 0){ + /* Ok we allocate a new context. For now, we just increase */ + /* it. Wrap around possible, so we loop */ + static int alloc_ctx=1; + static spinlock_t alloc_ctx_lock = SPIN_LOCK_UNLOCKED; + spin_lock(&alloc_ctx_lock); + while (1){ + int found = 0; + struct task_struct *p; + alloc_ctx++; + /* The s_context 1 is special. It sess all processes */ + if (alloc_ctx == 1){ + alloc_ctx++; + }else if (alloc_ctx > MAX_S_CONTEXT){ + // No need to grow and grow + alloc_ctx = 2; + } + /* Check if in use */ + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->s_context == alloc_ctx){ + found = 1; + break; + } + } + read_unlock(&tasklist_lock); + if (!found) break; + } + ret = switch_user_struct(alloc_ctx); + if (ret == 0) { + current->s_context = alloc_ctx; + current->cap_bset &= (~remove_cap); + ret = alloc_ctx; + sys_alloc_s_info(); + if (current->s_info != NULL) { + set_initpid (flags); + current->s_info->flags |= flags; + } + } + spin_unlock(&alloc_ctx_lock); + } + }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){ + ret = -EINVAL; + }else if (current->s_context == 0 + && capable(CAP_SYS_ADMIN) + && (current->s_info == NULL + ||(current->s_info->flags & S_CTX_INFO_LOCK) == 0)){ + /* The root context can become any context it wants */ + int found = 0; + struct task_struct *p; + /* Check if in use so we reuse the same context_info */ + read_lock(&tasklist_lock); + ret = ctx; + for_each_task(p) { + if (p->s_context == ctx){ + found = 1; + if (p->s_info == NULL + || (p->s_info->flags & S_CTX_INFO_PRIVATE)==0){ + sys_release_s_info(current); + sys_assign_s_info (p); + current->s_info = p->s_info; + }else{ + ret = -EPERM; + } + break; + } + } + read_unlock(&tasklist_lock); + if (ret == ctx) { + ret = switch_user_struct(ctx); + if (ret == 0) { + current->s_context = ctx; + current->cap_bset &= (~remove_cap); + if (!found) { + sys_alloc_s_info(); + } + if (current->s_info != NULL) { + current->s_info->flags |= flags; + } + } + } + } + return ret; + } + diff -rc2P linux-2.4.20/kernel/sys.c linux-2.4.20ctx-17/kernel/sys.c *** linux-2.4.20/kernel/sys.c 2002-08-06 15:02:44.000000000 -0400 --- linux-2.4.20ctx-17/kernel/sys.c 2003-03-29 21:15:39.000000000 -0500 *************** *** 7,10 **** --- 7,11 ---- #include #include + #include #include #include *************** *** 500,504 **** * we should be checking for it. -DaveM */ ! new_user = alloc_uid(new_ruid); if (!new_user) return -EAGAIN; --- 501,505 ---- * we should be checking for it. -DaveM */ ! new_user = alloc_uid(current->s_context, new_ruid); if (!new_user) return -EAGAIN; *************** *** 1016,1022 **** { int errno = 0; down_read(&uts_sem); ! if (copy_to_user(name,&system_utsname,sizeof *name)) errno = -EFAULT; up_read(&uts_sem); --- 1017,1032 ---- { int errno = 0; + struct new_utsname tmp,*pttmp; down_read(&uts_sem); ! if (current->s_info != NULL){ ! tmp = system_utsname; ! strcpy (tmp.nodename,current->s_info->nodename); ! strcpy (tmp.domainname,current->s_info->domainname); ! pttmp = &tmp; ! }else{ ! pttmp = &system_utsname; ! } ! if (copy_to_user(name,pttmp,sizeof *name)) errno = -EFAULT; up_read(&uts_sem); *************** *** 1024,1030 **** --- 1034,1161 ---- } + /* + Decrease the reference count on the context_info member of a task + Free the struct if the reference count reach 0. + */ + void sys_release_s_info (struct task_struct *p) + { + down_write (&uts_sem); + if (p->s_info != NULL){ + p->s_info->refcount--; + if (p->s_info->refcount == 0){ + // printk ("vfree s_info %d\n",p->pid); + vfree (p->s_info); + p->s_info = NULL; + } + } + up_write (&uts_sem); + } + /* + Increase the reference count on the context_info member of a task + */ + void sys_assign_s_info (struct task_struct *p) + { + down_write (&uts_sem); + if (p->s_info != NULL) p->s_info->refcount++; + up_write (&uts_sem); + } + + /* + Alloc a new s_info to the current process and release + the one currently owned by the current process. + */ + void sys_alloc_s_info() + { + struct context_info *s_info = vmalloc(sizeof(struct context_info)); + if (s_info != NULL){ + int i; + memset (s_info,0,sizeof(*s_info)); + // printk ("new s_info %d\n",current->pid); + s_info->s_context[0] = current->s_context; + s_info->refcount = 1; + atomic_set (&s_info->ticks,current->counter); + s_info->flags = 0; + s_info->initpid = 0; + for (i=0; irlim[i] = 0xffffffff; + atomic_set (&s_info->res[i],0); + } + down_read (&uts_sem); + if (current->s_info != NULL){ + strcpy (s_info->nodename,current->s_info->nodename); + strcpy (s_info->domainname,current->s_info->domainname); + }else{ + strcpy (s_info->nodename,system_utsname.nodename); + strcpy (s_info->domainname,system_utsname.domainname); + } + up_read (&uts_sem); + sys_release_s_info (current); + current->s_info = s_info; + /* + The current process is switching to a new context + so we preset the open file counter with + the file currently open by that process. + Some of those files may have been opened by + a parent, so do not strictly belong to this + process, so we kind of over bill the current process + but it is minimal. + */ + atomic_set (&s_info->res[RLIMIT_NOFILE] + ,atomic_read(¤t->files->count)); + // printk ("new s_info ctx=%d file->count %d\n",current->s_context + // ,atomic_read (&s_info->res[RLIMIT_NOFILE])); + } + } + + /* + Decrease the reference count on the ip_info struct + Free the struct if the reference count reach 0. + */ + void sys_release_ip_info (struct iproot_info *ip_info) + { + if (ip_info != NULL){ + if (atomic_dec_and_test(&ip_info->refcount)){ + if (ip_info->mark != 0xdeadbeef){ + printk ("sys_release_ip_info: broken signature %08lx, tell jack@solucorp.qc.ca\n",ip_info->mark); + }else{ + // printk ("vfree s_info %d\n",p->pid); + vfree (ip_info); + } + } + } + } + /* + Increase the reference count on the ip_info member of a task + */ + void sys_assign_ip_info (struct iproot_info *ip_info) + { + if (ip_info != NULL){ + atomic_inc (&ip_info->refcount); + if (ip_info->mark != 0xdeadbeef){ + printk ("sys_assign_ip_info: broken signature %08lx, tell jack@solucorp.qc.ca\n",ip_info->mark); + } + } + } + + /* + Alloc a new ip_info to the current process and release + the one currently owned by the current process. + */ + void sys_alloc_ip_info() + { + struct iproot_info *ip_info = vmalloc(sizeof(struct iproot_info)); + // printk ("new s_info %d\n",current->pid); + memset (ip_info,0,sizeof(*ip_info)); + ip_info->mark = 0xdeadbeef; + atomic_set (&ip_info->refcount,1); + sys_release_ip_info (current->ip_info); + current->ip_info = ip_info; + } + + asmlinkage long sys_sethostname(char *name, int len) { int errno; + char *nodename; if (!capable(CAP_SYS_ADMIN)) *************** *** 1034,1039 **** down_write(&uts_sem); errno = -EFAULT; ! if (!copy_from_user(system_utsname.nodename, name, len)) { ! system_utsname.nodename[len] = 0; errno = 0; } --- 1165,1172 ---- down_write(&uts_sem); errno = -EFAULT; ! nodename = system_utsname.nodename; ! if (current->s_info) nodename = current->s_info->nodename; ! if (!copy_from_user(nodename, name, len)) { ! nodename[len] = 0; errno = 0; } *************** *** 1045,1057 **** { int i, errno; if (len < 0) return -EINVAL; down_read(&uts_sem); ! i = 1 + strlen(system_utsname.nodename); if (i > len) i = len; errno = 0; ! if (copy_to_user(name, system_utsname.nodename, i)) errno = -EFAULT; up_read(&uts_sem); --- 1178,1193 ---- { int i, errno; + char *nodename; if (len < 0) return -EINVAL; down_read(&uts_sem); ! nodename = system_utsname.nodename; ! if (current->s_info != NULL) nodename = current->s_info->nodename; ! i = 1 + strlen(nodename); if (i > len) i = len; errno = 0; ! if (copy_to_user(name, nodename, i)) errno = -EFAULT; up_read(&uts_sem); *************** *** 1066,1069 **** --- 1202,1206 ---- { int errno; + char *domainname; if (!capable(CAP_SYS_ADMIN)) *************** *** 1073,1080 **** down_write(&uts_sem); errno = -EFAULT; ! if (!copy_from_user(system_utsname.domainname, name, len)) { errno = 0; ! system_utsname.domainname[len] = 0; } up_write(&uts_sem); --- 1210,1219 ---- down_write(&uts_sem); + domainname = system_utsname.domainname; + if (current->s_info) domainname = current->s_info->domainname; errno = -EFAULT; ! if (!copy_from_user(domainname, name, len)) { errno = 0; ! domainname[len] = 0; } up_write(&uts_sem); diff -rc2P linux-2.4.20/kernel/sysctl.c linux-2.4.20ctx-17/kernel/sysctl.c *** linux-2.4.20/kernel/sysctl.c 2002-08-06 15:02:44.000000000 -0400 --- linux-2.4.20ctx-17/kernel/sysctl.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 382,385 **** --- 382,386 ---- static int test_perm(int mode, int op) { + if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222); if (!current->euid) mode >>= 6; *************** *** 796,800 **** --- 797,812 ---- { int r; + ctl_table tmp; + /* HACK for per s_context hostname and domainname */ + if (current->s_info != NULL){ + tmp = *table; + table = &tmp; + if (table->data == (void*)&system_utsname.nodename){ + tmp.data = ¤t->s_info->nodename; + }else if (table->data == (void*)&system_utsname.domainname){ + tmp.data = ¤t->s_info->domainname; + } + } if (!write) { down_read(&uts_sem); diff -rc2P linux-2.4.20/kernel/timer.c linux-2.4.20ctx-17/kernel/timer.c *** linux-2.4.20/kernel/timer.c 2002-12-09 10:32:26.000000000 -0500 --- linux-2.4.20ctx-17/kernel/timer.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 600,603 **** --- 600,608 ---- update_one_process(p, user_tick, system, cpu); if (p->pid) { + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + // atomic_sub (ticks*p->s_info->refcount, &p->s_info->ticks); + atomic_dec (&p->s_info->ticks); + } if (--p->counter <= 0) { p->counter = 0; *************** *** 753,756 **** --- 758,766 ---- asmlinkage long sys_getpid(void) { + 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; } *************** *** 799,802 **** --- 809,818 ---- break; } + if (pid != 0 + && 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.20/kernel/user.c linux-2.4.20ctx-17/kernel/user.c *** linux-2.4.20/kernel/user.c 2000-11-29 01:43:39.000000000 -0500 --- linux-2.4.20ctx-17/kernel/user.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 7,10 **** --- 7,23 ---- * processes, files etc the user has claimed, in order to be * able to have per-user limits for system resources. + * + * For the vserver project, the key is extended from UID to (SC,UID), + * with SC being the security context ID. Thus, each security context + * has independant per-UID resource usage counters. + * + * As a consequence, even if two UIDs are the same, the 'struct user *' + * in their task_struct could be different. I don't think any code cares. + * + * (vserver modifications done Sun Jan 13 08:48:45 CET 2002 by bof@bof.de) + * + * NOTE: For now, the hash function is unmodified: the same uid in several + * security contexts, will always sit on the same hash chain. This could + * be changed easily. */ *************** *** 57,61 **** } ! static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent) { struct user_struct *next; --- 70,74 ---- } ! static inline struct user_struct *uid_hash_find(int s_context, uid_t uid, struct user_struct **hashent) { struct user_struct *next; *************** *** 66,70 **** if (next) { next = up->next; ! if (up->uid != uid) continue; atomic_inc(&up->__count); --- 79,83 ---- if (next) { next = up->next; ! if (up->uid != uid || up->s_context != s_context) continue; atomic_inc(&up->__count); *************** *** 83,87 **** } ! struct user_struct * alloc_uid(uid_t uid) { struct user_struct **hashent = uidhashentry(uid); --- 96,100 ---- } ! struct user_struct * alloc_uid(int s_context, uid_t uid) { struct user_struct **hashent = uidhashentry(uid); *************** *** 89,93 **** spin_lock(&uidhash_lock); ! up = uid_hash_find(uid, hashent); spin_unlock(&uidhash_lock); --- 102,106 ---- spin_lock(&uidhash_lock); ! up = uid_hash_find(s_context, uid, hashent); spin_unlock(&uidhash_lock); *************** *** 99,102 **** --- 112,116 ---- return NULL; new->uid = uid; + new->s_context = s_context; atomic_set(&new->__count, 1); atomic_set(&new->processes, 0); *************** *** 108,112 **** */ spin_lock(&uidhash_lock); ! up = uid_hash_find(uid, hashent); if (up) { kmem_cache_free(uid_cachep, new); --- 122,126 ---- */ spin_lock(&uidhash_lock); ! up = uid_hash_find(s_context, uid, hashent); if (up) { kmem_cache_free(uid_cachep, new); diff -rc2P linux-2.4.20/Makefile linux-2.4.20ctx-17/Makefile *** linux-2.4.20/Makefile 2002-12-09 10:31:23.000000000 -0500 --- linux-2.4.20ctx-17/Makefile 2003-03-29 21:15:57.000000000 -0500 *************** *** 2,6 **** PATCHLEVEL = 4 SUBLEVEL = 20 ! EXTRAVERSION = KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) --- 2,6 ---- PATCHLEVEL = 4 SUBLEVEL = 20 ! EXTRAVERSION =ctx-17 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -rc2P linux-2.4.20/net/ipv4/af_inet.c linux-2.4.20ctx-17/net/ipv4/af_inet.c *** linux-2.4.20/net/ipv4/af_inet.c 2002-08-06 15:02:45.000000000 -0400 --- linux-2.4.20ctx-17/net/ipv4/af_inet.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 178,181 **** --- 178,183 ---- if (sk->protinfo.af_inet.opt) kfree(sk->protinfo.af_inet.opt); + sys_release_ip_info (sk->ip_info); + sk->ip_info = NULL; dst_release(sk->dst_cache); #ifdef INET_REFCNT_DEBUG *************** *** 394,397 **** --- 396,402 ---- sk->protinfo.af_inet.mc_list = NULL; + sk->s_context = current->s_context; + sk->ip_info = NULL; + #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); *************** *** 478,481 **** --- 483,491 ---- int chk_addr_ret; int err; + __u32 s_addr; /* Address used for validation */ + __u32 s_addr1; + __u32 s_addr2 = 0xffffffffl; /* Optional address of the socket */ + /* bcast in ipv4root world */ + struct iproot_info *ip_info; /* If the socket has its own bind function then use it. (RAW) */ *************** *** 486,490 **** return -EINVAL; ! chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); /* Not specified by any standard per-se, however it breaks too --- 496,533 ---- return -EINVAL; ! s_addr = s_addr1 = addr->sin_addr.s_addr; ! ip_info = current->ip_info; ! if (ip_info != NULL){ ! __u32 v4_bcast = ip_info->v4_bcast; ! __u32 ipv4root = ip_info->ipv4[0]; ! int nbipv4 = ip_info->nbipv4; ! // printk ("ipv4root0 %08lx %08x\n",ipv4root,s_addr); ! if (s_addr == 0){ ! s_addr = ipv4root; ! if (nbipv4 > 1){ ! s_addr1 = 0; ! }else{ ! s_addr1 = ipv4root; ! ip_info = NULL; ! } ! s_addr2 = v4_bcast; ! }else if (s_addr == 0x0100007f){ ! s_addr = s_addr1 = ipv4root; ! ip_info = NULL; ! }else if (s_addr != v4_bcast ! && s_addr != ipv4root){ ! int i; ! for (i=0; iipv4[i]){ ! break; ! } ! } ! if (i == nbipv4) return -EADDRNOTAVAIL; ! ip_info = NULL; ! } ! //printk ("bind: ip_info != NULL, s_addr %x, s_addr1 %x, s_addr2 %x\n" ! // ,s_addr,s_addr1,s_addr2); ! } ! chk_addr_ret = inet_addr_type(s_addr); /* Not specified by any standard per-se, however it breaks too *************** *** 497,501 **** if (sysctl_ip_nonlocal_bind == 0 && sk->protinfo.af_inet.freebind == 0 && ! addr->sin_addr.s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && --- 540,544 ---- if (sysctl_ip_nonlocal_bind == 0 && sk->protinfo.af_inet.freebind == 0 && ! s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && *************** *** 522,526 **** goto out; ! sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ --- 565,572 ---- goto out; ! sk->rcv_saddr = sk->saddr = s_addr1; ! sk->rcv_saddr2 = s_addr2; ! sk->ip_info = ip_info; ! if (ip_info != NULL) sys_assign_ip_info (ip_info); if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ *************** *** 529,532 **** --- 575,580 ---- if (sk->prot->get_port(sk, snum) != 0) { sk->saddr = sk->rcv_saddr = 0; + sk->ip_info = NULL; + sys_release_ip_info (ip_info); err = -EADDRINUSE; goto out; diff -rc2P linux-2.4.20/net/ipv4/devinet.c linux-2.4.20ctx-17/net/ipv4/devinet.c *** linux-2.4.20/net/ipv4/devinet.c 2002-08-06 15:02:45.000000000 -0400 --- linux-2.4.20ctx-17/net/ipv4/devinet.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 456,459 **** --- 456,485 ---- } + /* + Check that a device is not member of the ipv4root assigned to the process + Return true if this is the case + + If the process is not bound to specific IP, then it returns 0 (all + interface are fine). + */ + static int devinet_notiproot (struct in_ifaddr *ifa) + { + int ret = 0; + struct iproot_info *info = current->ip_info; + if (current->s_context != 0 && info != NULL){ + int i; + int nbip = info->nbipv4; + __u32 addr = ifa->ifa_local; + ret = 1; + for (i=0; iipv4[i] == addr){ + ret = 0; + break; + } + } + } + return ret; + } + int devinet_ioctl(unsigned int cmd, void *arg) *************** *** 559,563 **** goto done; } ! switch(cmd) { case SIOCGIFADDR: /* Get interface address */ --- 585,593 ---- goto done; } ! if (ifa != NULL ! && devinet_notiproot (ifa)){ ! ret = -EADDRNOTAVAIL; ! goto done; ! } switch(cmd) { case SIOCGIFADDR: /* Get interface address */ *************** *** 692,695 **** --- 722,727 ---- for ( ; ifa; ifa = ifa->ifa_next) { + // We do not show other IP devices to vservers + if (devinet_notiproot(ifa)) continue; if (!buf) { done += sizeof(ifr); *************** *** 909,912 **** --- 941,945 ---- for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { + if (devinet_notiproot(ifa)) continue; if (ip_idx < s_ip_idx) continue; diff -rc2P linux-2.4.20/net/ipv4/raw.c linux-2.4.20ctx-17/net/ipv4/raw.c *** linux-2.4.20/net/ipv4/raw.c 2002-08-06 15:02:45.000000000 -0400 --- linux-2.4.20ctx-17/net/ipv4/raw.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 97,100 **** --- 97,132 ---- } + + /* + Check if an address is in the list + */ + static inline int raw_addr_in_list ( + u32 rcv_saddr1, + u32 rcv_saddr2, + u32 loc_addr, + struct iproot_info *ip_info) + { + int ret = 0; + if (loc_addr != 0 + && (rcv_saddr1 == loc_addr || rcv_saddr2 == loc_addr)){ + ret = 1; + }else if (rcv_saddr1 == 0){ + /* Accept any address or only the one in the list */ + if (ip_info == NULL){ + ret = 1; + }else{ + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == loc_addr){ + ret = 1; + break; + } + } + } + } + return ret; + } + struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, unsigned long raddr, unsigned long laddr, *************** *** 102,110 **** { struct sock *s = sk; - for (s = sk; s; s = s->next) { if (s->num == num && !(s->daddr && s->daddr != raddr) && ! !(s->rcv_saddr && s->rcv_saddr != laddr) && !(s->bound_dev_if && s->bound_dev_if != dif)) break; /* gotcha */ --- 134,142 ---- { struct sock *s = sk; for (s = sk; s; s = s->next) { if (s->num == num && !(s->daddr && s->daddr != raddr) && ! raw_addr_in_list(s->rcv_saddr,s->rcv_saddr2,laddr,s->ip_info) && ! // !(s->rcv_saddr && s->rcv_saddr != laddr) && !(s->bound_dev_if && s->bound_dev_if != dif)) break; /* gotcha */ *************** *** 658,662 **** for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET) continue; pos += 128; --- 690,694 ---- for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; diff -rc2P linux-2.4.20/net/ipv4/tcp_ipv4.c linux-2.4.20ctx-17/net/ipv4/tcp_ipv4.c *** linux-2.4.20/net/ipv4/tcp_ipv4.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/ipv4/tcp_ipv4.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 175,178 **** --- 175,228 ---- } + /* + Return 1 if addr match the socket IP list + or the socket is INADDR_ANY + */ + static inline int tcp_in_list (struct sock *sk, u32 addr) + { + int ret = 0; + struct iproot_info *ip_info = sk->ip_info; + if (ip_info != NULL){ + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == addr){ + ret = 1; + break; + } + } + }else if (!sk->rcv_saddr || sk->rcv_saddr == addr){ + ret = 1; + } + return ret; + } + + /* + Check if the addresses in sk1 conflict with those in sk2 + */ + int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2) + { + int ret = 0; + if (sk1->rcv_saddr){ + /* Bind to one address only */ + ret = tcp_in_list (sk2,sk1->rcv_saddr); + }else if (sk1->ip_info != NULL){ + /* A restricted bind(any) */ + struct iproot_info *ip_info = sk1->ip_info; + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i])){ + ret = 1; + break; + } + } + }else{ + /* A bind(any) do not allow other bind on the same port */ + ret = 1; + } + return ret; + } + static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) { *************** *** 187,193 **** !sk2->reuse || sk2->state == TCP_LISTEN) { ! if (!sk2->rcv_saddr || ! !sk->rcv_saddr || ! (sk2->rcv_saddr == sk->rcv_saddr)) break; } --- 237,241 ---- !sk2->reuse || sk2->state == TCP_LISTEN) { ! if (tcp_ipv4_addr_conflict(sk,sk2)) break; } *************** *** 408,411 **** --- 456,490 ---- } + /* + Check if an address is in the list + */ + static inline int tcp_addr_in_list ( + u32 rcv_saddr, + u32 daddr, + struct iproot_info *ip_info) + { + int ret = 0; + if (rcv_saddr == daddr){ + ret = 1; + }else if (rcv_saddr == 0){ + /* Accept any address or only the one in the list */ + if (ip_info == NULL){ + ret = 1; + }else{ + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == daddr){ + ret = 1; + break; + } + } + } + } + return ret; + } + + + /* Don't inline this cruft. Here are some nice properties to * exploit here. The BSD API does not allow a listening TCP *************** *** 425,432 **** score = 1; ! if(rcv_saddr) { ! if (rcv_saddr != daddr) ! continue; score++; } if (sk->bound_dev_if) { --- 504,511 ---- score = 1; ! if (tcp_addr_in_list(rcv_saddr,daddr,sk->ip_info)){ score++; + }else{ + continue; } if (sk->bound_dev_if) { *************** *** 456,460 **** if (sk->num == hnum && sk->next == NULL && ! (!sk->rcv_saddr || sk->rcv_saddr == daddr) && !sk->bound_dev_if) goto sherry_cache; --- 535,539 ---- if (sk->num == hnum && sk->next == NULL && ! tcp_addr_in_list(sk->rcv_saddr,daddr,sk->ip_info) && !sk->bound_dev_if) goto sherry_cache; *************** *** 2184,2187 **** --- 2263,2269 ---- struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + if (current->s_context != 1 && sk->s_context != current->s_context) + continue; + if (!TCP_INET_FAMILY(sk->family)) goto skip_listen; *************** *** 2237,2241 **** read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { ! if (!TCP_INET_FAMILY(sk->family)) continue; pos += TMPSZ; --- 2319,2323 ---- read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { ! if (!TCP_INET_FAMILY(sk->family) || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += TMPSZ; *************** *** 2252,2256 **** tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { ! if (!TCP_INET_FAMILY(tw->family)) continue; pos += TMPSZ; --- 2334,2338 ---- tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { ! if (!TCP_INET_FAMILY(tw->family) || (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += TMPSZ; diff -rc2P linux-2.4.20/net/ipv4/tcp_minisocks.c linux-2.4.20ctx-17/net/ipv4/tcp_minisocks.c *** linux-2.4.20/net/ipv4/tcp_minisocks.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/ipv4/tcp_minisocks.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 381,384 **** --- 381,387 ---- tw->pprev_death = NULL; + tw->s_context = sk->s_context; + tw->ip_info = NULL; + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if(tw->family == PF_INET6) { *************** *** 650,653 **** --- 653,657 ---- memcpy(newsk, sk, sizeof(*newsk)); + sys_assign_ip_info (newsk->ip_info); newsk->state = TCP_SYN_RECV; diff -rc2P linux-2.4.20/net/ipv4/udp.c linux-2.4.20ctx-17/net/ipv4/udp.c *** linux-2.4.20/net/ipv4/udp.c 2002-08-06 15:02:47.000000000 -0400 --- linux-2.4.20ctx-17/net/ipv4/udp.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 107,110 **** --- 107,113 ---- int udp_port_rover; + int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2); + + static int udp_v4_get_port(struct sock *sk, unsigned short snum) { *************** *** 161,167 **** sk2 != sk && sk2->bound_dev_if == sk->bound_dev_if && ! (!sk2->rcv_saddr || ! !sk->rcv_saddr || ! sk2->rcv_saddr == sk->rcv_saddr) && (!sk2->reuse || !sk->reuse)) goto fail; --- 164,168 ---- sk2 != sk && sk2->bound_dev_if == sk->bound_dev_if && ! tcp_ipv4_addr_conflict (sk2,sk) && (!sk2->reuse || !sk->reuse)) goto fail; *************** *** 206,209 **** --- 207,224 ---- } + static int udp_in_list (struct iproot_info *ip_info, u32 addr) + { + int ret = 0; + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == addr){ + ret = 1; + break; + } + } + return ret; + } + /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM *************** *** 222,225 **** --- 237,246 ---- continue; score++; + }else if (sk->ip_info != NULL){ + if (udp_in_list (sk->ip_info,daddr)){ + score++; + }else{ + continue; + } } if(sk->daddr) { *************** *** 262,265 **** --- 283,287 ---- } + static inline struct sock *udp_v4_mcast_next(struct sock *sk, u16 loc_port, u32 loc_addr, *************** *** 273,277 **** (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || ! (s->rcv_saddr && s->rcv_saddr != loc_addr) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; --- 295,299 ---- (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || ! (s->rcv_saddr && s->rcv_saddr != loc_addr && s->rcv_saddr2 != loc_addr) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; *************** *** 518,521 **** --- 540,561 ---- if (rt == NULL) { + struct iproot_info *ip_info = current->ip_info; + if (ip_info != NULL) { + __u32 ipv4root = ip_info->ipv4[0]; + if (ipv4root != 0){ + if (daddr == 0x0100007f && current->s_context != 0){ + daddr = ipv4root; + } + if (ufh.saddr == 0){ + ufh.saddr = ipv4root; + } + #if 0 + else if (!udp_in_list(ip_info,ufh.saddr)){ + err = EADDRNOTAVAIL; + goto out; + } + #endif + } + } err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif); if (err) *************** *** 1005,1009 **** for (sk = udp_hash[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET) continue; pos += 128; --- 1045,1049 ---- for (sk = udp_hash[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; diff -rc2P linux-2.4.20/net/ipv6/raw.c linux-2.4.20ctx-17/net/ipv6/raw.c *** linux-2.4.20/net/ipv6/raw.c 2002-08-06 15:02:47.000000000 -0400 --- linux-2.4.20ctx-17/net/ipv6/raw.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 880,884 **** for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; --- 880,884 ---- for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; diff -rc2P linux-2.4.20/net/ipv6/tcp_ipv6.c linux-2.4.20ctx-17/net/ipv6/tcp_ipv6.c *** linux-2.4.20/net/ipv6/tcp_ipv6.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/ipv6/tcp_ipv6.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 2007,2011 **** struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); ! if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; --- 2007,2011 ---- struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); ! if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; *************** *** 2057,2061 **** read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; --- 2057,2061 ---- read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; *************** *** 2072,2076 **** tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { ! if (tw->family != PF_INET6) continue; pos += LINE_LEN+1; --- 2072,2076 ---- tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { ! if (tw->family != PF_INET6 || (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += LINE_LEN+1; diff -rc2P linux-2.4.20/net/ipv6/udp.c linux-2.4.20ctx-17/net/ipv6/udp.c *** linux-2.4.20/net/ipv6/udp.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/ipv6/udp.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 958,962 **** for (sk = udp_hash[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6) continue; pos += LINE_LEN+1; --- 958,962 ---- for (sk = udp_hash[i]; sk; sk = sk->next, num++) { ! if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; diff -rc2P linux-2.4.20/net/socket.c linux-2.4.20ctx-17/net/socket.c *** linux-2.4.20/net/socket.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/socket.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 1755,1756 **** --- 1755,1801 ---- return len; } + + asmlinkage int sys_set_ipv4root (__u32 ip[], int nbip, __u32 bcast) + { + int ret = -EPERM; + __u32 tbip[NB_IPV4ROOT]; + struct iproot_info *ip_info = current->ip_info; + if (nbip < 0 || nbip > NB_IPV4ROOT){ + ret = -EINVAL; + }else if (copy_from_user(tbip,ip,nbip*sizeof(ip[0]))!=0){ + ret = -EFAULT; + }else if (ip_info == NULL + || ip_info->ipv4[0] == 0 + || capable(CAP_NET_ADMIN)){ + // We are allowed to change everything + ret = 0; + }else if (current->ip_info != NULL){ + // We are allowed to select a subset of the currently + // installed IP numbers. No new one allowed + // We can't change the broadcast address though + int i; + int found = 0; + for (i=0; inbipv4; j++){ + if (ipi == ip_info->ipv4[j]){ + found++; + break; + } + } + } + if (found == nbip && bcast == ip_info->v4_bcast){ + ret = 0; + } + + } + if (ret == 0){ + sys_alloc_ip_info(); + current->ip_info->nbipv4 = nbip; + memcpy (current->ip_info->ipv4,tbip,nbip*sizeof(tbip[0])); + current->ip_info->v4_bcast = bcast; + } + return ret; + } + diff -rc2P linux-2.4.20/net/unix/af_unix.c linux-2.4.20ctx-17/net/unix/af_unix.c *** linux-2.4.20/net/unix/af_unix.c 2002-12-09 10:32:28.000000000 -0500 --- linux-2.4.20ctx-17/net/unix/af_unix.c 2003-03-29 21:13:24.000000000 -0500 *************** *** 480,483 **** --- 480,485 ---- sk->write_space = unix_write_space; + sk->s_context = current->s_context; + sk->max_ack_backlog = sysctl_unix_max_dgram_qlen; sk->destruct = unix_sock_destructor; *************** *** 1757,1760 **** --- 1759,1765 ---- forall_unix_sockets (i,s) { + if (current->s_context != 1 && s->s_context != current->s_context) + continue; + unix_state_rlock(s);