Commit 025f143c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleeding_edge-2.5

into kroah.com:/home/greg/linux/BK/lsm-2.5
parents 59ece965 776e2421
...@@ -1670,6 +1670,7 @@ D: USB I/O Edgeport driver, USB Serial IrDA driver ...@@ -1670,6 +1670,7 @@ D: USB I/O Edgeport driver, USB Serial IrDA driver
D: USB Bluetooth driver, USB Skeleton driver D: USB Bluetooth driver, USB Skeleton driver
D: bits and pieces of USB core code. D: bits and pieces of USB core code.
D: PCI Hotplug core, PCI Hotplug Compaq driver modifications D: PCI Hotplug core, PCI Hotplug Compaq driver modifications
D: portions of the Linux Security Module (LSM) framework
N: Russell Kroll N: Russell Kroll
E: rkroll@exploits.org E: rkroll@exploits.org
...@@ -2155,6 +2156,14 @@ N: Thomas Molina ...@@ -2155,6 +2156,14 @@ N: Thomas Molina
E: tmolina@cox.net E: tmolina@cox.net
D: bug fixes, documentation, minor hackery D: bug fixes, documentation, minor hackery
N: James Morris
E: jmorris@intercode.com.au
W: http://www.intercode.com.au/jmorris/
D: Netfilter, Linux Security Modules (LSM).
S: PO Box 707
S: Spit Junction NSW 2088
S: Australia
N: David Mosberger-Tang N: David Mosberger-Tang
E: davidm@hpl.hp.com if IA-64 related, else David.Mosberger@acm.org E: davidm@hpl.hp.com if IA-64 related, else David.Mosberger@acm.org
D: Linux/Alpha and Linux/ia64 D: Linux/Alpha and Linux/ia64
...@@ -2649,6 +2658,11 @@ S: Markusstrasse 18 ...@@ -2649,6 +2658,11 @@ S: Markusstrasse 18
S: 8006 Zuerich S: 8006 Zuerich
S: Switzerland S: Switzerland
N: Wayne Salamon
E: wsalamon@tislabs.com
E: wsalamon@nai.com
D: portions of the Linux Security Module (LSM) framework and security modules
N: Robert Sanders N: Robert Sanders
E: gt8134b@prism.gatech.edu E: gt8134b@prism.gatech.edu
D: Dosemu D: Dosemu
...@@ -2775,6 +2789,11 @@ S: 10 Stockalls Place ...@@ -2775,6 +2789,11 @@ S: 10 Stockalls Place
S: Minto, NSW, 2566 S: Minto, NSW, 2566
S: Australia S: Australia
N: Stephen Smalley
E: sds@tislabs.com
E: ssmalley@nai.com
D: portions of the Linux Security Module (LSM) framework and security modules
N: Chris Smith N: Chris Smith
E: csmith@convex.com E: csmith@convex.com
D: Read only HPFS filesystem D: Read only HPFS filesystem
...@@ -3041,6 +3060,11 @@ S: C. Huysmansstraat 12 ...@@ -3041,6 +3060,11 @@ S: C. Huysmansstraat 12
S: B-3128 Baal S: B-3128 Baal
S: Belgium S: Belgium
N: Chris Vance
E: cvance@tislabs.com
E: cvance@nai.com
D: portions of the Linux Security Module (LSM) framework and security modules
N: Petr Vandrovec N: Petr Vandrovec
E: vandrove@vc.cvut.cz E: vandrove@vc.cvut.cz
D: Small contributions to ncpfs D: Small contributions to ncpfs
...@@ -3273,6 +3297,14 @@ S: 60 Clifton Road ...@@ -3273,6 +3297,14 @@ S: 60 Clifton Road
S: Cambridge. CB1 7EG S: Cambridge. CB1 7EG
S: England S: England
N: Chris Wright
E: chris@wirex.com
D: hacking on LSM framework and security modules.
S: c/o WireX
S: 920 SW 3rd, Ste. 100
S: Portland, OR 97204
S: USA
N: Frank Xia N: Frank Xia
E: qx@math.columbia.edu E: qx@math.columbia.edu
D: Xiafs filesystem [defunct] D: Xiafs filesystem [defunct]
......
...@@ -393,4 +393,5 @@ fi ...@@ -393,4 +393,5 @@ fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -658,4 +658,5 @@ dep_bool ' Kernel low-level debugging messages via footbridge serial port' CO ...@@ -658,4 +658,5 @@ dep_bool ' Kernel low-level debugging messages via footbridge serial port' CO
dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -228,5 +228,7 @@ if [ "$CONFIG_PROFILE" = "y" ]; then ...@@ -228,5 +228,7 @@ if [ "$CONFIG_PROFILE" = "y" ]; then
int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
fi fi
source lib/Config.in
endmenu endmenu
source security/Config.in
source lib/Config.in
...@@ -263,3 +263,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then ...@@ -263,3 +263,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
fi fi
endmenu endmenu
source security/Config.in
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/security.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -1100,6 +1101,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ...@@ -1100,6 +1101,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
/* are we already being traced? */ /* are we already being traced? */
if (current->ptrace & PT_PTRACED) if (current->ptrace & PT_PTRACED)
goto out; goto out;
ret = security_ops->ptrace(current->parent, current);
if (ret)
goto out;
current->ptrace |= PT_PTRACED; current->ptrace |= PT_PTRACED;
ret = 0; ret = 0;
goto out; goto out;
......
...@@ -547,4 +547,5 @@ fi ...@@ -547,4 +547,5 @@ fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -503,4 +503,5 @@ if [ "$CONFIG_SMP" != "y" ]; then ...@@ -503,4 +503,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
fi fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -248,4 +248,5 @@ if [ "$CONFIG_SMP" != "y" ]; then ...@@ -248,4 +248,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
fi fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -200,4 +200,5 @@ comment 'Kernel hacking' ...@@ -200,4 +200,5 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -623,3 +623,6 @@ if [ "$CONFIG_4xx" = "y" -o "$CONFIG_GT64260" = "y" \ ...@@ -623,3 +623,6 @@ if [ "$CONFIG_4xx" = "y" -o "$CONFIG_GT64260" = "y" \
bool 'Support for early boot texts over serial port' CONFIG_SERIAL_TEXT_DEBUG bool 'Support for early boot texts over serial port' CONFIG_SERIAL_TEXT_DEBUG
fi fi
endmenu endmenu
source security/Config.in
...@@ -226,4 +226,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then ...@@ -226,4 +226,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
fi fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -75,4 +75,5 @@ comment 'Kernel hacking' ...@@ -75,4 +75,5 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -78,4 +78,5 @@ comment 'Kernel hacking' ...@@ -78,4 +78,5 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -369,4 +369,5 @@ if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then ...@@ -369,4 +369,5 @@ if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
fi fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -242,4 +242,5 @@ comment 'Kernel hacking' ...@@ -242,4 +242,5 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -293,4 +293,5 @@ fi ...@@ -293,4 +293,5 @@ fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -229,4 +229,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then ...@@ -229,4 +229,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
fi fi
endmenu endmenu
source security/Config.in
source lib/Config.in source lib/Config.in
...@@ -1458,6 +1458,10 @@ static int tty_fasync(int fd, struct file * filp, int on) ...@@ -1458,6 +1458,10 @@ static int tty_fasync(int fd, struct file * filp, int on)
if (!waitqueue_active(&tty->read_wait)) if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = 1; tty->minimum_to_wake = 1;
if (filp->f_owner.pid == 0) { if (filp->f_owner.pid == 0) {
retval = security_ops->file_set_fowner(filp);
if (retval)
return retval;
filp->f_owner.pid = (-tty->pgrp) ? : current->pid; filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
filp->f_owner.uid = current->uid; filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid; filp->f_owner.euid = current->euid;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/dnotify.h> #include <linux/dnotify.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/security.h>
/* Taken over from the old code... */ /* Taken over from the old code... */
...@@ -151,10 +152,14 @@ int notify_change(struct dentry * dentry, struct iattr * attr) ...@@ -151,10 +152,14 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
} }
} }
if (inode->i_op && inode->i_op->setattr) if (inode->i_op && inode->i_op->setattr) {
error = inode->i_op->setattr(dentry, attr); error = security_ops->inode_setattr(dentry, attr);
else { if (!error)
error = inode->i_op->setattr(dentry, attr);
} else {
error = inode_change_ok(inode, attr); error = inode_change_ok(inode, attr);
if (!error)
error = security_ops->inode_setattr(dentry, attr);
if (!error) { if (!error) {
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
......
...@@ -68,6 +68,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) ...@@ -68,6 +68,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
struct dnotify_struct **prev; struct dnotify_struct **prev;
struct inode *inode; struct inode *inode;
fl_owner_t id = current->files; fl_owner_t id = current->files;
int error;
if ((arg & ~DN_MULTISHOT) == 0) { if ((arg & ~DN_MULTISHOT) == 0) {
dnotify_flush(filp, id); dnotify_flush(filp, id);
...@@ -93,6 +94,13 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) ...@@ -93,6 +94,13 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
} }
prev = &odn->dn_next; prev = &odn->dn_next;
} }
error = security_ops->file_set_fowner(filp);
if (error) {
write_unlock(&dn_lock);
return error;
}
filp->f_owner.pid = current->pid; filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid; filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid; filp->f_owner.euid = current->euid;
......
...@@ -1316,6 +1316,9 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) ...@@ -1316,6 +1316,9 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
error = -EIO; error = -EIO;
if (!f->f_op || !f->f_op->read || !f->f_op->write) if (!f->f_op || !f->f_op->read || !f->f_op->write)
goto out_f; goto out_f;
error = security_ops->quota_on(f);
if (error)
goto out_f;
inode = f->f_dentry->d_inode; inode = f->f_dentry->d_inode;
error = -EACCES; error = -EACCES;
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/iobuf.h> #include <linux/iobuf.h>
#include <linux/security.h>
#include <asm/poll.h> #include <asm/poll.h>
#include <asm/siginfo.h> #include <asm/siginfo.h>
...@@ -305,6 +306,13 @@ static long do_fcntl(unsigned int fd, unsigned int cmd, ...@@ -305,6 +306,13 @@ static long do_fcntl(unsigned int fd, unsigned int cmd,
break; break;
case F_SETOWN: case F_SETOWN:
lock_kernel(); lock_kernel();
err = security_ops->file_set_fowner(filp);
if (err) {
unlock_kernel();
break;
}
filp->f_owner.pid = arg; filp->f_owner.pid = arg;
filp->f_owner.uid = current->uid; filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid; filp->f_owner.euid = current->euid;
...@@ -353,6 +361,12 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -353,6 +361,12 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
if (!filp) if (!filp)
goto out; goto out;
err = security_ops->file_fcntl(filp, cmd, arg);
if (err) {
fput(filp);
return err;
}
err = do_fcntl(fd, cmd, arg, filp); err = do_fcntl(fd, cmd, arg, filp);
fput(filp); fput(filp);
...@@ -371,6 +385,13 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg ...@@ -371,6 +385,13 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg
if (!filp) if (!filp)
goto out; goto out;
err = security_ops->file_fcntl(filp, cmd, arg);
if (err) {
fput(filp);
return err;
}
err = -EBADF;
switch (cmd) { switch (cmd) {
case F_GETLK64: case F_GETLK64:
err = fcntl_getlk64(filp, (struct flock64 *) arg); err = fcntl_getlk64(filp, (struct flock64 *) arg);
...@@ -409,6 +430,10 @@ static void send_sigio_to_task(struct task_struct *p, ...@@ -409,6 +430,10 @@ static void send_sigio_to_task(struct task_struct *p,
(fown->euid ^ p->suid) && (fown->euid ^ p->uid) && (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
(fown->uid ^ p->suid) && (fown->uid ^ p->uid)) (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
return; return;
if (security_ops->file_send_sigiotask(p, fown, fd, reason))
return;
switch (fown->signum) { switch (fown->signum) {
siginfo_t si; siginfo_t si;
default: default:
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/iobuf.h> #include <linux/iobuf.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/security.h>
/* sysctl tunables... */ /* sysctl tunables... */
struct files_stat_struct files_stat = {0, 0, NR_FILE}; struct files_stat_struct files_stat = {0, 0, NR_FILE};
...@@ -43,6 +44,12 @@ struct file * get_empty_filp(void) ...@@ -43,6 +44,12 @@ struct file * get_empty_filp(void)
files_stat.nr_free_files--; files_stat.nr_free_files--;
new_one: new_one:
memset(f, 0, sizeof(*f)); memset(f, 0, sizeof(*f));
if (security_ops->file_alloc_security(f)) {
list_add(&f->f_list, &free_list);
files_stat.nr_free_files++;
file_list_unlock();
return NULL;
}
atomic_set(&f->f_count,1); atomic_set(&f->f_count,1);
f->f_version = ++event; f->f_version = ++event;
f->f_uid = current->fsuid; f->f_uid = current->fsuid;
...@@ -117,6 +124,7 @@ void __fput(struct file * file) ...@@ -117,6 +124,7 @@ void __fput(struct file * file)
if (file->f_op && file->f_op->release) if (file->f_op && file->f_op->release)
file->f_op->release(inode, file); file->f_op->release(inode, file);
security_ops->file_free_security(file);
fops_put(file->f_op); fops_put(file->f_op);
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITE)
put_write_access(inode); put_write_access(inode);
...@@ -149,6 +157,7 @@ struct file * fget(unsigned int fd) ...@@ -149,6 +157,7 @@ struct file * fget(unsigned int fd)
void put_filp(struct file *file) void put_filp(struct file *file)
{ {
if(atomic_dec_and_test(&file->f_count)) { if(atomic_dec_and_test(&file->f_count)) {
security_ops->file_free_security(file);
file_list_lock(); file_list_lock();
list_del(&file->f_list); list_del(&file->f_list);
list_add(&file->f_list, &free_list); list_add(&file->f_list, &free_list);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/security.h>
/* /*
* This is needed for the following functions: * This is needed for the following functions:
...@@ -100,6 +101,14 @@ static struct inode *alloc_inode(struct super_block *sb) ...@@ -100,6 +101,14 @@ static struct inode *alloc_inode(struct super_block *sb)
if (inode) { if (inode) {
struct address_space * const mapping = &inode->i_data; struct address_space * const mapping = &inode->i_data;
inode->i_security = NULL;
if (security_ops->inode_alloc_security(inode)) {
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
kmem_cache_free(inode_cachep, (inode));
return NULL;
}
inode->i_sb = sb; inode->i_sb = sb;
inode->i_dev = sb->s_dev; inode->i_dev = sb->s_dev;
inode->i_blkbits = sb->s_blocksize_bits; inode->i_blkbits = sb->s_blocksize_bits;
...@@ -137,6 +146,7 @@ static void destroy_inode(struct inode *inode) ...@@ -137,6 +146,7 @@ static void destroy_inode(struct inode *inode)
{ {
if (inode_has_buffers(inode)) if (inode_has_buffers(inode))
BUG(); BUG();
security_ops->inode_free_security(inode);
if (inode->i_sb->s_op->destroy_inode) if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode); inode->i_sb->s_op->destroy_inode(inode);
else else
...@@ -793,6 +803,8 @@ void generic_delete_inode(struct inode *inode) ...@@ -793,6 +803,8 @@ void generic_delete_inode(struct inode *inode)
if (inode->i_data.nrpages) if (inode->i_data.nrpages)
truncate_inode_pages(&inode->i_data, 0); truncate_inode_pages(&inode->i_data, 0);
security_ops->inode_delete(inode);
if (op && op->delete_inode) { if (op && op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode; void (*delete)(struct inode *) = op->delete_inode;
if (!is_bad_inode(inode)) if (!is_bad_inode(inode))
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/ioctls.h> #include <asm/ioctls.h>
...@@ -57,6 +58,13 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -57,6 +58,13 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
if (!filp) if (!filp)
goto out; goto out;
error = 0; error = 0;
error = security_ops->file_ioctl(filp, cmd, arg);
if (error) {
fput(filp);
goto out;
}
lock_kernel(); lock_kernel();
switch (cmd) { switch (cmd) {
case FIOCLEX: case FIOCLEX:
......
...@@ -1309,6 +1309,11 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) ...@@ -1309,6 +1309,11 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
fl->fl_next = *before; fl->fl_next = *before;
*before = fl; *before = fl;
list_add(&fl->fl_link, &file_lock_list); list_add(&fl->fl_link, &file_lock_list);
error = security_ops->file_set_fowner(filp);
if (error)
goto out_unlock;
filp->f_owner.pid = current->pid; filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid; filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid; filp->f_owner.euid = current->euid;
...@@ -1354,6 +1359,11 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) ...@@ -1354,6 +1359,11 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
if (error < 0) if (error < 0)
goto out_putf; goto out_putf;
error = security_ops->file_lock(filp, cmd,
(cmd & LOCK_NB) ? 0 : 1);
if (error)
goto out_putf;
error = flock_lock_file(filp, lock, error = flock_lock_file(filp, lock,
(cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
...@@ -1484,6 +1494,11 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l) ...@@ -1484,6 +1494,11 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
goto out; goto out;
} }
error = security_ops->file_lock(filp, file_lock->fl_type,
cmd == F_SETLKW);
if (error)
goto out;
if (filp->f_op && filp->f_op->lock != NULL) { if (filp->f_op && filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp, cmd, file_lock); error = filp->f_op->lock(filp, cmd, file_lock);
if (error < 0) if (error < 0)
...@@ -1603,6 +1618,11 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l) ...@@ -1603,6 +1618,11 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l)
goto out; goto out;
} }
error = security_ops->file_lock(filp, file_lock->fl_type,
cmd == F_SETLKW64);
if (error)
goto out;
if (filp->f_op && filp->f_op->lock != NULL) { if (filp->f_op && filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp, cmd, file_lock); error = filp->f_op->lock(filp, cmd, file_lock);
if (error < 0) if (error < 0)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/dnotify.h> #include <linux/dnotify.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/security.h>
#include <asm/namei.h> #include <asm/namei.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -204,9 +205,20 @@ int vfs_permission(struct inode * inode, int mask) ...@@ -204,9 +205,20 @@ int vfs_permission(struct inode * inode, int mask)
int permission(struct inode * inode,int mask) int permission(struct inode * inode,int mask)
{ {
int retval;
int submask;
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission) if (inode->i_op && inode->i_op->permission)
return inode->i_op->permission(inode, mask); retval = inode->i_op->permission(inode, submask);
return vfs_permission(inode, mask); else
retval = vfs_permission(inode, submask);
if (retval)
return retval;
return security_ops->inode_permission(inode, mask);
} }
/* /*
...@@ -318,15 +330,17 @@ static inline int exec_permission_lite(struct inode *inode) ...@@ -318,15 +330,17 @@ static inline int exec_permission_lite(struct inode *inode)
mode >>= 3; mode >>= 3;
if (mode & MAY_EXEC) if (mode & MAY_EXEC)
return 0; goto ok;
if ((inode->i_mode & S_IXUGO) && capable(CAP_DAC_OVERRIDE)) if ((inode->i_mode & S_IXUGO) && capable(CAP_DAC_OVERRIDE))
return 0; goto ok;
if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_READ_SEARCH)) if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_READ_SEARCH))
return 0; goto ok;
return -EACCES; return -EACCES;
ok:
return security_ops->inode_permission_lite(inode, MAY_EXEC);
} }
/* /*
...@@ -358,8 +372,10 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i ...@@ -358,8 +372,10 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i
result = dir->i_op->lookup(dir, dentry); result = dir->i_op->lookup(dir, dentry);
if (result) if (result)
dput(dentry); dput(dentry);
else else {
result = dentry; result = dentry;
security_ops->inode_post_lookup(dir, result);
}
} }
up(&dir->i_sem); up(&dir->i_sem);
return result; return result;
...@@ -388,7 +404,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i ...@@ -388,7 +404,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i
*/ */
static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
int err; int err = -ELOOP;
if (current->link_count >= 5) if (current->link_count >= 5)
goto loop; goto loop;
if (current->total_link_count >= 40) if (current->total_link_count >= 40)
...@@ -397,6 +413,9 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -397,6 +413,9 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
schedule(); schedule();
} }
err = security_ops->inode_follow_link(dentry, nd);
if (err)
goto loop;
current->link_count++; current->link_count++;
current->total_link_count++; current->total_link_count++;
UPDATE_ATIME(dentry->d_inode); UPDATE_ATIME(dentry->d_inode);
...@@ -405,7 +424,7 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -405,7 +424,7 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
return err; return err;
loop: loop:
path_release(nd); path_release(nd);
return -ELOOP; return err;
} }
int follow_up(struct vfsmount **mnt, struct dentry **dentry) int follow_up(struct vfsmount **mnt, struct dentry **dentry)
...@@ -897,9 +916,10 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ...@@ -897,9 +916,10 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
if (!new) if (!new)
goto out; goto out;
dentry = inode->i_op->lookup(inode, new); dentry = inode->i_op->lookup(inode, new);
if (!dentry) if (!dentry) {
dentry = new; dentry = new;
else security_ops->inode_post_lookup(inode, dentry);
} else
dput(new); dput(new);
} }
out: out:
...@@ -1103,14 +1123,17 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode) ...@@ -1103,14 +1123,17 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
if (!dir->i_op || !dir->i_op->create) if (!dir->i_op || !dir->i_op->create)
return -EACCES; /* shouldn't it be ENOSYS? */ return -EACCES; /* shouldn't it be ENOSYS? */
DQUOT_INIT(dir);
mode &= S_IALLUGO; mode &= S_IALLUGO;
mode |= S_IFREG; mode |= S_IFREG;
error = security_ops->inode_create(dir, dentry, mode);
if (error)
return error;
DQUOT_INIT(dir);
error = dir->i_op->create(dir, dentry, mode); error = dir->i_op->create(dir, dentry, mode);
if (!error) if (!error) {
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
security_ops->inode_post_create(dir, dentry, mode);
}
return error; return error;
} }
...@@ -1211,6 +1234,11 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ...@@ -1211,6 +1234,11 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
acc_mode = ACC_MODE(flag); acc_mode = ACC_MODE(flag);
/* Allow the LSM permission hook to distinguish append
access from general write access. */
if (flag & O_APPEND)
acc_mode |= MAY_APPEND;
/* /*
* The simplest case - just a plain lookup. * The simplest case - just a plain lookup.
*/ */
...@@ -1316,6 +1344,9 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ...@@ -1316,6 +1344,9 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
* stored in nd->last.name and we will have to putname() it when we * stored in nd->last.name and we will have to putname() it when we
* are done. Procfs-like symlinks just set LAST_BIND. * are done. Procfs-like symlinks just set LAST_BIND.
*/ */
error = security_ops->inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
UPDATE_ATIME(dentry->d_inode); UPDATE_ATIME(dentry->d_inode);
error = dentry->d_inode->i_op->follow_link(dentry, nd); error = dentry->d_inode->i_op->follow_link(dentry, nd);
dput(dentry); dput(dentry);
...@@ -1379,10 +1410,16 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) ...@@ -1379,10 +1410,16 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
if (!dir->i_op || !dir->i_op->mknod) if (!dir->i_op || !dir->i_op->mknod)
return -EPERM; return -EPERM;
error = security_ops->inode_mknod(dir, dentry, mode, dev);
if (error)
return error;
DQUOT_INIT(dir); DQUOT_INIT(dir);
error = dir->i_op->mknod(dir, dentry, mode, dev); error = dir->i_op->mknod(dir, dentry, mode, dev);
if (!error) if (!error) {
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
security_ops->inode_post_mknod(dir, dentry, mode, dev);
}
return error; return error;
} }
...@@ -1440,11 +1477,17 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -1440,11 +1477,17 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (!dir->i_op || !dir->i_op->mkdir) if (!dir->i_op || !dir->i_op->mkdir)
return -EPERM; return -EPERM;
DQUOT_INIT(dir);
mode &= (S_IRWXUGO|S_ISVTX); mode &= (S_IRWXUGO|S_ISVTX);
error = security_ops->inode_mkdir(dir, dentry, mode);
if (error)
return error;
DQUOT_INIT(dir);
error = dir->i_op->mkdir(dir, dentry, mode); error = dir->i_op->mkdir(dir, dentry, mode);
if (!error) if (!error) {
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
security_ops->inode_post_mkdir(dir,dentry, mode);
}
return error; return error;
} }
...@@ -1527,9 +1570,12 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1527,9 +1570,12 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
if (d_mountpoint(dentry)) if (d_mountpoint(dentry))
error = -EBUSY; error = -EBUSY;
else { else {
error = dir->i_op->rmdir(dir, dentry); error = security_ops->inode_rmdir(dir, dentry);
if (!error) if (!error) {
dentry->d_inode->i_flags |= S_DEAD; error = dir->i_op->rmdir(dir, dentry);
if (!error)
dentry->d_inode->i_flags |= S_DEAD;
}
} }
up(&dentry->d_inode->i_sem); up(&dentry->d_inode->i_sem);
if (!error) { if (!error) {
...@@ -1597,8 +1643,12 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1597,8 +1643,12 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
down(&dentry->d_inode->i_sem); down(&dentry->d_inode->i_sem);
if (d_mountpoint(dentry)) if (d_mountpoint(dentry))
error = -EBUSY; error = -EBUSY;
else else {
error = dir->i_op->unlink(dir, dentry); error = security_ops->inode_unlink(dir, dentry);
if (!error) {
error = dir->i_op->unlink(dir, dentry);
}
}
up(&dentry->d_inode->i_sem); up(&dentry->d_inode->i_sem);
if (!error) { if (!error) {
d_delete(dentry); d_delete(dentry);
...@@ -1659,10 +1709,16 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) ...@@ -1659,10 +1709,16 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
if (!dir->i_op || !dir->i_op->symlink) if (!dir->i_op || !dir->i_op->symlink)
return -EPERM; return -EPERM;
error = security_ops->inode_symlink(dir, dentry, oldname);
if (error)
return error;
DQUOT_INIT(dir); DQUOT_INIT(dir);
error = dir->i_op->symlink(dir, dentry, oldname); error = dir->i_op->symlink(dir, dentry, oldname);
if (!error) if (!error) {
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
security_ops->inode_post_symlink(dir, dentry, oldname);
}
return error; return error;
} }
...@@ -1724,12 +1780,18 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de ...@@ -1724,12 +1780,18 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
if (S_ISDIR(old_dentry->d_inode->i_mode)) if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM; return -EPERM;
error = security_ops->inode_link(old_dentry, dir, new_dentry);
if (error)
return error;
down(&old_dentry->d_inode->i_sem); down(&old_dentry->d_inode->i_sem);
DQUOT_INIT(dir); DQUOT_INIT(dir);
error = dir->i_op->link(old_dentry, dir, new_dentry); error = dir->i_op->link(old_dentry, dir, new_dentry);
up(&old_dentry->d_inode->i_sem); up(&old_dentry->d_inode->i_sem);
if (!error) if (!error) {
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
security_ops->inode_post_link(old_dentry, dir, new_dentry);
}
return error; return error;
} }
...@@ -1821,9 +1883,13 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1821,9 +1883,13 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
* If we are going to change the parent - check write permissions, * If we are going to change the parent - check write permissions,
* we'll need to flip '..'. * we'll need to flip '..'.
*/ */
if (new_dir != old_dir) if (new_dir != old_dir) {
error = permission(old_dentry->d_inode, MAY_WRITE); error = permission(old_dentry->d_inode, MAY_WRITE);
if (error)
return error;
}
error = security_ops->inode_rename(old_dir, old_dentry, new_dir, new_dentry);
if (error) if (error)
return error; return error;
...@@ -1844,8 +1910,11 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1844,8 +1910,11 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
d_rehash(new_dentry); d_rehash(new_dentry);
dput(new_dentry); dput(new_dentry);
} }
if (!error) if (!error) {
d_move(old_dentry,new_dentry); d_move(old_dentry,new_dentry);
security_ops->inode_post_rename(old_dir, old_dentry,
new_dir, new_dentry);
}
return error; return error;
} }
...@@ -1855,6 +1924,10 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1855,6 +1924,10 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
struct inode *target; struct inode *target;
int error; int error;
error = security_ops->inode_rename(old_dir, old_dentry, new_dir, new_dentry);
if (error)
return error;
dget(new_dentry); dget(new_dentry);
target = new_dentry->d_inode; target = new_dentry->d_inode;
if (target) if (target)
...@@ -1867,6 +1940,7 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1867,6 +1940,7 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
/* The following d_move() should become unconditional */ /* The following d_move() should become unconditional */
if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
d_move(old_dentry, new_dentry); d_move(old_dentry, new_dentry);
security_ops->inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
} }
if (target) if (target)
up(&target->i_sem); up(&target->i_sem);
......
...@@ -288,6 +288,10 @@ static int do_umount(struct vfsmount *mnt, int flags) ...@@ -288,6 +288,10 @@ static int do_umount(struct vfsmount *mnt, int flags)
struct super_block * sb = mnt->mnt_sb; struct super_block * sb = mnt->mnt_sb;
int retval = 0; int retval = 0;
retval = security_ops->sb_umount(mnt, flags);
if (retval)
return retval;
/* /*
* If we may have to abort operations to get out of this * If we may have to abort operations to get out of this
* mount, and they will themselves hold resources we must * mount, and they will themselves hold resources we must
...@@ -337,6 +341,7 @@ static int do_umount(struct vfsmount *mnt, int flags) ...@@ -337,6 +341,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
DQUOT_OFF(sb); DQUOT_OFF(sb);
acct_auto_close(sb); acct_auto_close(sb);
unlock_kernel(); unlock_kernel();
security_ops->sb_umount_close(mnt);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
} }
retval = -EBUSY; retval = -EBUSY;
...@@ -346,6 +351,8 @@ static int do_umount(struct vfsmount *mnt, int flags) ...@@ -346,6 +351,8 @@ static int do_umount(struct vfsmount *mnt, int flags)
retval = 0; retval = 0;
} }
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
if (retval)
security_ops->sb_umount_busy(mnt);
up_write(&current->namespace->sem); up_write(&current->namespace->sem);
return retval; return retval;
} }
...@@ -463,6 +470,10 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) ...@@ -463,6 +470,10 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
if (IS_DEADDIR(nd->dentry->d_inode)) if (IS_DEADDIR(nd->dentry->d_inode))
goto out_unlock; goto out_unlock;
err = security_ops->sb_check_sb(mnt, nd);
if (err)
goto out_unlock;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) { if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) {
struct list_head head; struct list_head head;
...@@ -475,6 +486,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) ...@@ -475,6 +486,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
out_unlock: out_unlock:
up(&nd->dentry->d_inode->i_sem); up(&nd->dentry->d_inode->i_sem);
if (!err)
security_ops->sb_post_addmount(mnt, nd);
return err; return err;
} }
...@@ -544,6 +557,8 @@ static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data) ...@@ -544,6 +557,8 @@ static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data)
if (!err) if (!err)
nd->mnt->mnt_flags=mnt_flags; nd->mnt->mnt_flags=mnt_flags;
up_write(&sb->s_umount); up_write(&sb->s_umount);
if (!err)
security_ops->sb_post_remount(nd->mnt, flags, data);
return err; return err;
} }
...@@ -726,6 +741,10 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, ...@@ -726,6 +741,10 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
if (retval) if (retval)
return retval; return retval;
retval = security_ops->sb_mount(dev_name, &nd, type_page, flags, data_page);
if (retval)
goto dput_out;
if (flags & MS_REMOUNT) if (flags & MS_REMOUNT)
retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
data_page); data_page);
...@@ -736,6 +755,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, ...@@ -736,6 +755,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
else else
retval = do_add_mount(&nd, type_page, flags, mnt_flags, retval = do_add_mount(&nd, type_page, flags, mnt_flags,
dev_name, data_page); dev_name, data_page);
dput_out:
path_release(&nd); path_release(&nd);
return retval; return retval;
} }
...@@ -919,6 +939,12 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) ...@@ -919,6 +939,12 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
if (error) if (error)
goto out1; goto out1;
error = security_ops->sb_pivotroot(&old_nd, &new_nd);
if (error) {
path_release(&old_nd);
goto out1;
}
read_lock(&current->fs->lock); read_lock(&current->fs->lock);
user_nd.mnt = mntget(current->fs->rootmnt); user_nd.mnt = mntget(current->fs->rootmnt);
user_nd.dentry = dget(current->fs->root); user_nd.dentry = dget(current->fs->root);
...@@ -963,6 +989,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) ...@@ -963,6 +989,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
attach_mnt(new_nd.mnt, &root_parent); attach_mnt(new_nd.mnt, &root_parent);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
chroot_fs_refs(&user_nd, &new_nd); chroot_fs_refs(&user_nd, &new_nd);
security_ops->sb_post_pivotroot(&user_nd, &new_nd);
error = 0; error = 0;
path_release(&root_parent); path_release(&root_parent);
path_release(&parent_nd); path_release(&parent_nd);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/iobuf.h> #include <linux/iobuf.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -30,6 +31,9 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf) ...@@ -30,6 +31,9 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf)
retval = -ENOSYS; retval = -ENOSYS;
if (sb->s_op && sb->s_op->statfs) { if (sb->s_op && sb->s_op->statfs) {
memset(buf, 0, sizeof(struct statfs)); memset(buf, 0, sizeof(struct statfs));
retval = security_ops->sb_statfs(sb);
if (retval)
return retval;
retval = sb->s_op->statfs(sb, buf); retval = sb->s_op->statfs(sb, buf);
} }
} }
......
...@@ -394,7 +394,7 @@ static struct file_operations proc_info_file_operations = { ...@@ -394,7 +394,7 @@ static struct file_operations proc_info_file_operations = {
}; };
#define MAY_PTRACE(p) \ #define MAY_PTRACE(p) \
(p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED)) (p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(current,p)==0))
static int mem_open(struct inode* inode, struct file* file) static int mem_open(struct inode* inode, struct file* file)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/security.h>
/* Check validity of quotactl */ /* Check validity of quotactl */
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
...@@ -96,7 +97,8 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t ...@@ -96,7 +97,8 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT) else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
return 0;
return security_ops->quotactl (cmd, type, id, sb);
} }
/* Resolve device pathname to superblock */ /* Resolve device pathname to superblock */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/dnotify.h> #include <linux/dnotify.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -117,6 +118,13 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) ...@@ -117,6 +118,13 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
file = fget(fd); file = fget(fd);
if (!file) if (!file)
goto bad; goto bad;
retval = security_ops->file_llseek(file);
if (retval) {
fput(file);
goto bad;
}
retval = -EINVAL; retval = -EINVAL;
if (origin <= 2) { if (origin <= 2) {
loff_t res = llseek(file, offset, origin); loff_t res = llseek(file, offset, origin);
...@@ -142,6 +150,11 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, ...@@ -142,6 +150,11 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
file = fget(fd); file = fget(fd);
if (!file) if (!file)
goto bad; goto bad;
retval = security_ops->file_llseek(file);
if (retval)
goto out_putf;
retval = -EINVAL; retval = -EINVAL;
if (origin > 2) if (origin > 2)
goto out_putf; goto out_putf;
...@@ -176,9 +189,12 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos) ...@@ -176,9 +189,12 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count); ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
if (!ret) { if (!ret) {
ret = file->f_op->read(file, buf, count, pos); ret = security_ops->file_permission (file, MAY_READ);
if (ret > 0) if (!ret) {
dnotify_parent(file->f_dentry, DN_ACCESS); ret = file->f_op->read(file, buf, count, pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS);
}
} }
return ret; return ret;
...@@ -198,9 +214,12 @@ ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos) ...@@ -198,9 +214,12 @@ ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos)
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count); ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
if (!ret) { if (!ret) {
ret = file->f_op->write(file, buf, count, pos); ret = security_ops->file_permission (file, MAY_WRITE);
if (ret > 0) if (!ret) {
dnotify_parent(file->f_dentry, DN_MODIFY); ret = file->f_op->write(file, buf, count, pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY);
}
} }
return ret; return ret;
...@@ -384,8 +403,11 @@ asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector, ...@@ -384,8 +403,11 @@ asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector,
if (!file) if (!file)
goto bad_file; goto bad_file;
if (file->f_op && (file->f_mode & FMODE_READ) && if (file->f_op && (file->f_mode & FMODE_READ) &&
(file->f_op->readv || file->f_op->read)) (file->f_op->readv || file->f_op->read)) {
ret = do_readv_writev(VERIFY_WRITE, file, vector, count); ret = security_ops->file_permission (file, MAY_READ);
if (!ret)
ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
}
fput(file); fput(file);
bad_file: bad_file:
...@@ -404,8 +426,11 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector, ...@@ -404,8 +426,11 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
if (!file) if (!file)
goto bad_file; goto bad_file;
if (file->f_op && (file->f_mode & FMODE_WRITE) && if (file->f_op && (file->f_mode & FMODE_WRITE) &&
(file->f_op->writev || file->f_op->write)) (file->f_op->writev || file->f_op->write)) {
ret = do_readv_writev(VERIFY_READ, file, vector, count); ret = security_ops->file_permission (file, MAY_WRITE);
if (!ret)
ret = do_readv_writev(VERIFY_READ, file, vector, count);
}
fput(file); fput(file);
bad_file: bad_file:
......
...@@ -20,6 +20,11 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) ...@@ -20,6 +20,11 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf)
int res = -ENOTDIR; int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir) if (!file->f_op || !file->f_op->readdir)
goto out; goto out;
res = security_ops->file_permission(file, MAY_READ);
if (res)
goto out;
down(&inode->i_sem); down(&inode->i_sem);
res = -ENOENT; res = -ENOENT;
if (!IS_DEADDIR(inode)) { if (!IS_DEADDIR(inode)) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/highuid.h> #include <linux/highuid.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -36,6 +37,11 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) ...@@ -36,6 +37,11 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int retval;
retval = security_ops->inode_getattr(mnt, dentry);
if (retval)
return retval;
if (inode->i_op->getattr) if (inode->i_op->getattr)
return inode->i_op->getattr(mnt, dentry, stat); return inode->i_op->getattr(mnt, dentry, stat);
...@@ -232,8 +238,11 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz) ...@@ -232,8 +238,11 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
error = -EINVAL; error = -EINVAL;
if (inode->i_op && inode->i_op->readlink) { if (inode->i_op && inode->i_op->readlink) {
UPDATE_ATIME(inode); error = security_ops->inode_readlink(nd.dentry);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz); if (!error) {
UPDATE_ATIME(inode);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
}
} }
path_release(&nd); path_release(&nd);
} }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <linux/buffer_head.h> /* for fsync_super() */ #include <linux/buffer_head.h> /* for fsync_super() */
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/security.h>
void get_filesystem(struct file_system_type *fs); void get_filesystem(struct file_system_type *fs);
void put_filesystem(struct file_system_type *fs); void put_filesystem(struct file_system_type *fs);
struct file_system_type *get_fs_type(const char *name); struct file_system_type *get_fs_type(const char *name);
...@@ -49,6 +51,11 @@ static struct super_block *alloc_super(void) ...@@ -49,6 +51,11 @@ static struct super_block *alloc_super(void)
struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER); struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
if (s) { if (s) {
memset(s, 0, sizeof(struct super_block)); memset(s, 0, sizeof(struct super_block));
if (security_ops->sb_alloc_security(s)) {
kfree(s);
s = NULL;
goto out;
}
INIT_LIST_HEAD(&s->s_dirty); INIT_LIST_HEAD(&s->s_dirty);
INIT_LIST_HEAD(&s->s_io); INIT_LIST_HEAD(&s->s_io);
INIT_LIST_HEAD(&s->s_locked_inodes); INIT_LIST_HEAD(&s->s_locked_inodes);
...@@ -67,6 +74,7 @@ static struct super_block *alloc_super(void) ...@@ -67,6 +74,7 @@ static struct super_block *alloc_super(void)
s->dq_op = sb_dquot_ops; s->dq_op = sb_dquot_ops;
s->s_qcop = sb_quotactl_ops; s->s_qcop = sb_quotactl_ops;
} }
out:
return s; return s;
} }
...@@ -78,6 +86,7 @@ static struct super_block *alloc_super(void) ...@@ -78,6 +86,7 @@ static struct super_block *alloc_super(void)
*/ */
static inline void destroy_super(struct super_block *s) static inline void destroy_super(struct super_block *s)
{ {
security_ops->sb_free_security(s);
kfree(s); kfree(s);
} }
......
...@@ -85,11 +85,16 @@ setxattr(struct dentry *d, char *name, void *value, size_t size, int flags) ...@@ -85,11 +85,16 @@ setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
error = security_ops->inode_setxattr(d, kname, kvalue,
size, flags);
if (error)
goto out;
down(&d->d_inode->i_sem); down(&d->d_inode->i_sem);
error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
up(&d->d_inode->i_sem); up(&d->d_inode->i_sem);
} }
out:
xattr_free(kvalue, size); xattr_free(kvalue, size);
return error; return error;
} }
...@@ -158,6 +163,9 @@ getxattr(struct dentry *d, char *name, void *value, size_t size) ...@@ -158,6 +163,9 @@ getxattr(struct dentry *d, char *name, void *value, size_t size)
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
error = security_ops->inode_getxattr(d, kname);
if (error)
goto out;
down(&d->d_inode->i_sem); down(&d->d_inode->i_sem);
error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
up(&d->d_inode->i_sem); up(&d->d_inode->i_sem);
...@@ -166,6 +174,7 @@ getxattr(struct dentry *d, char *name, void *value, size_t size) ...@@ -166,6 +174,7 @@ getxattr(struct dentry *d, char *name, void *value, size_t size)
if (kvalue && error > 0) if (kvalue && error > 0)
if (copy_to_user(value, kvalue, error)) if (copy_to_user(value, kvalue, error))
error = -EFAULT; error = -EFAULT;
out:
xattr_free(kvalue, size); xattr_free(kvalue, size);
return error; return error;
} }
...@@ -227,6 +236,9 @@ listxattr(struct dentry *d, char *list, size_t size) ...@@ -227,6 +236,9 @@ listxattr(struct dentry *d, char *list, size_t size)
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
error = security_ops->inode_listxattr(d);
if (error)
goto out;
down(&d->d_inode->i_sem); down(&d->d_inode->i_sem);
error = d->d_inode->i_op->listxattr(d, klist, size); error = d->d_inode->i_op->listxattr(d, klist, size);
up(&d->d_inode->i_sem); up(&d->d_inode->i_sem);
...@@ -235,6 +247,7 @@ listxattr(struct dentry *d, char *list, size_t size) ...@@ -235,6 +247,7 @@ listxattr(struct dentry *d, char *list, size_t size)
if (klist && error > 0) if (klist && error > 0)
if (copy_to_user(list, klist, error)) if (copy_to_user(list, klist, error))
error = -EFAULT; error = -EFAULT;
out:
xattr_free(klist, size); xattr_free(klist, size);
return error; return error;
} }
...@@ -298,10 +311,14 @@ removexattr(struct dentry *d, char *name) ...@@ -298,10 +311,14 @@ removexattr(struct dentry *d, char *name)
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->removexattr) { if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
error = security_ops->inode_removexattr(d, kname);
if (error)
goto out;
down(&d->d_inode->i_sem); down(&d->d_inode->i_sem);
error = d->d_inode->i_op->removexattr(d, kname); error = d->d_inode->i_op->removexattr(d, kname);
up(&d->d_inode->i_sem); up(&d->d_inode->i_sem);
} }
out:
return error; return error;
} }
......
...@@ -72,6 +72,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time; ...@@ -72,6 +72,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define MAY_EXEC 1 #define MAY_EXEC 1
#define MAY_WRITE 2 #define MAY_WRITE 2
#define MAY_READ 4 #define MAY_READ 4
#define MAY_APPEND 8
#define FMODE_READ 1 #define FMODE_READ 1
#define FMODE_WRITE 2 #define FMODE_WRITE 2
...@@ -399,6 +400,7 @@ struct inode { ...@@ -399,6 +400,7 @@ struct inode {
unsigned char i_sock; unsigned char i_sock;
atomic_t i_writecount; atomic_t i_writecount;
void *i_security;
__u32 i_generation; __u32 i_generation;
union { union {
void *generic_ip; void *generic_ip;
...@@ -429,6 +431,7 @@ struct fown_struct { ...@@ -429,6 +431,7 @@ struct fown_struct {
int pid; /* pid or -pgrp where SIGIO should be sent */ int pid; /* pid or -pgrp where SIGIO should be sent */
uid_t uid, euid; /* uid/euid of process setting the owner */ uid_t uid, euid; /* uid/euid of process setting the owner */
int signum; /* posix.1b rt signal to be delivered on IO */ int signum; /* posix.1b rt signal to be delivered on IO */
void *security;
}; };
static inline void inode_add_bytes(struct inode *inode, loff_t bytes) static inline void inode_add_bytes(struct inode *inode, loff_t bytes)
...@@ -492,6 +495,7 @@ struct file { ...@@ -492,6 +495,7 @@ struct file {
struct file_ra_state f_ra; struct file_ra_state f_ra;
unsigned long f_version; unsigned long f_version;
void *f_security;
/* needed for tty driver, and maybe others */ /* needed for tty driver, and maybe others */
void *private_data; void *private_data;
...@@ -645,6 +649,7 @@ struct super_block { ...@@ -645,6 +649,7 @@ struct super_block {
int s_count; int s_count;
int s_syncing; int s_syncing;
atomic_t s_active; atomic_t s_active;
void *s_security;
struct list_head s_dirty; /* dirty inodes */ struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */ struct list_head s_io; /* parked for writeback */
......
This diff is collapsed.
...@@ -845,6 +845,7 @@ void prepare_namespace(void) ...@@ -845,6 +845,7 @@ void prepare_namespace(void)
sys_umount("/dev", 0); sys_umount("/dev", 0);
sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot("."); sys_chroot(".");
security_ops->sb_post_mountroot();
mount_devfs_fs (); mount_devfs_fs ();
} }
......
...@@ -195,6 +195,7 @@ asmlinkage long sys_acct(const char *name) ...@@ -195,6 +195,7 @@ asmlinkage long sys_acct(const char *name)
{ {
struct file *file = NULL; struct file *file = NULL;
char *tmp; char *tmp;
int error;
if (!capable(CAP_SYS_PACCT)) if (!capable(CAP_SYS_PACCT))
return -EPERM; return -EPERM;
...@@ -221,6 +222,10 @@ asmlinkage long sys_acct(const char *name) ...@@ -221,6 +222,10 @@ asmlinkage long sys_acct(const char *name)
} }
} }
error = security_ops->acct(file);
if (error)
return error;
spin_lock(&acct_globals.lock); spin_lock(&acct_globals.lock);
acct_file_reopen(file); acct_file_reopen(file);
spin_unlock(&acct_globals.lock); spin_unlock(&acct_globals.lock);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/iobuf.h> #include <linux/iobuf.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/security.h>
/* /*
* This is needed for the following functions: * This is needed for the following functions:
* - try_to_release_page * - try_to_release_page
...@@ -1143,6 +1144,10 @@ static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t cou ...@@ -1143,6 +1144,10 @@ static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t cou
if (retval) if (retval)
goto fput_in; goto fput_in;
retval = security_ops->file_permission (in_file, MAY_READ);
if (retval)
goto fput_in;
/* /*
* Get output file, and verify that it is ok.. * Get output file, and verify that it is ok..
*/ */
...@@ -1160,6 +1165,10 @@ static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t cou ...@@ -1160,6 +1165,10 @@ static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t cou
if (retval) if (retval)
goto fput_out; goto fput_out;
retval = security_ops->file_permission (out_file, MAY_WRITE);
if (retval)
goto fput_out;
retval = 0; retval = 0;
if (count) { if (count) {
read_descriptor_t desc; read_descriptor_t desc;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -475,6 +476,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon ...@@ -475,6 +476,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
} }
} }
error = security_ops->file_mmap(file, prot, flags);
if (error)
return error;
/* Clear old maps */ /* Clear old maps */
error = -ENOMEM; error = -ENOMEM;
munmap_back: munmap_back:
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -306,6 +307,10 @@ asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot ...@@ -306,6 +307,10 @@ asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot
goto out; goto out;
} }
error = security_ops->file_mprotect(vma, prot);
if (error)
goto out;
if (vma->vm_end > end) { if (vma->vm_end > end) {
error = mprotect_fixup(vma, &prev, nstart, end, newflags); error = mprotect_fixup(vma, &prev, nstart, end, newflags);
goto out; goto out;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/security.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -216,6 +217,9 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) ...@@ -216,6 +217,9 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++) for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
{ {
int new_fd; int new_fd;
err = security_ops->file_receive(fp[i]);
if (err)
break;
err = get_unused_fd(); err = get_unused_fd();
if (err < 0) if (err < 0)
break; break;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment