Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 70805
b: refs/heads/master
c: b537677
h: refs/heads/master
i:
  70803: 8e2c2b2
v: v3
  • Loading branch information
Serge E. Hallyn authored and Linus Torvalds committed Oct 17, 2007
1 parent 17af140 commit 229a368
Show file tree
Hide file tree
Showing 16 changed files with 419 additions and 74 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57c521ce6125e15e99e56c902cb8da96bee7b36d
refs/heads/master: b53767719b6cd8789392ea3e7e2eb7b8906898f0
9 changes: 9 additions & 0 deletions trunk/fs/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
attr->ia_atime = now;
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
if (ia_valid & ATTR_KILL_PRIV) {
attr->ia_valid &= ~ATTR_KILL_PRIV;
ia_valid &= ~ATTR_KILL_PRIV;
error = security_inode_need_killpriv(dentry);
if (error > 0)
error = security_inode_killpriv(dentry);
if (error)
return error;
}
if (ia_valid & ATTR_KILL_SUID) {
attr->ia_valid &= ~ATTR_KILL_SUID;
if (mode & S_ISUID) {
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,

/* Revoke setuid/setgid bit on chown/chgrp */
if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
iap->ia_valid |= ATTR_KILL_SUID;
iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
iap->ia_valid |= ATTR_KILL_SGID;

Expand Down Expand Up @@ -937,7 +937,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
static void kill_suid(struct dentry *dentry)
{
struct iattr ia;
ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;

mutex_lock(&dentry->d_inode->i_mutex);
notify_change(dentry, &ia);
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,8 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
newattrs.ia_gid = group;
}
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
Expand Down
13 changes: 9 additions & 4 deletions trunk/fs/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,13 +824,18 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
int killsuid, killpriv;
ssize_t ret;
int err;
int err = 0;

err = should_remove_suid(out->f_path.dentry);
if (unlikely(err)) {
killpriv = security_inode_need_killpriv(out->f_path.dentry);
killsuid = should_remove_suid(out->f_path.dentry);
if (unlikely(killsuid || killpriv)) {
mutex_lock(&inode->i_mutex);
err = __remove_suid(out->f_path.dentry, err);
if (killpriv)
err = security_inode_killpriv(out->f_path.dentry);
if (!err && killsuid)
err = __remove_suid(out->f_path.dentry, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/binfmts.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ struct linux_binprm{
int sh_bang;
struct file * file;
int e_uid, e_gid;
kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
kernel_cap_t cap_inheritable, cap_permitted;
bool cap_effective;
void *security;
int argc, envc;
char * filename; /* Name of binary as seen by procps */
Expand Down
48 changes: 34 additions & 14 deletions trunk/include/linux/capability.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
* This is <linux/capability.h>
*
* Andrew G. Morgan <morgan@transmeta.com>
* Andrew G. Morgan <morgan@kernel.org>
* Alexander Kjeldaas <astor@guardian.no>
* with help from Aleph1, Roland Buresund and Andrew Main.
*
* See here for the libcap library ("POSIX draft" compliance):
*
* ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/
*/
* ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
*/

#ifndef _LINUX_CAPABILITY_H
#define _LINUX_CAPABILITY_H
Expand All @@ -28,23 +28,41 @@ struct task_struct;
following structure to such a composite is better handled in a user
library since the draft standard requires the use of malloc/free
etc.. */

#define _LINUX_CAPABILITY_VERSION 0x19980330

typedef struct __user_cap_header_struct {
__u32 version;
int pid;
} __user *cap_user_header_t;

typedef struct __user_cap_data_struct {
__u32 effective;
__u32 permitted;
__u32 inheritable;
} __user *cap_user_data_t;

#ifdef __KERNEL__

#include <asm/current.h>
#define XATTR_CAPS_SUFFIX "capability"
#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX

#define XATTR_CAPS_SZ (3*sizeof(__le32))
#define VFS_CAP_REVISION_MASK 0xFF000000
#define VFS_CAP_REVISION_1 0x01000000

#define VFS_CAP_REVISION VFS_CAP_REVISION_1

#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
#define VFS_CAP_FLAGS_EFFECTIVE 0x000001

struct vfs_cap_data {
__u32 magic_etc; /* Little endian */
struct {
__u32 permitted; /* Little endian */
__u32 inheritable; /* Little endian */
} data[1];
};

#ifdef __KERNEL__

/* #define STRICT_CAP_T_TYPECHECKS */

Expand All @@ -59,15 +77,15 @@ typedef struct kernel_cap_struct {
typedef __u32 kernel_cap_t;

#endif

#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))

#endif


/**
** POSIX-draft defined capabilities.
** POSIX-draft defined capabilities.
**/

/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
Expand All @@ -87,7 +105,7 @@ typedef __u32 kernel_cap_t;
defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */

#define CAP_DAC_READ_SEARCH 2

/* Overrides all restrictions about allowed operations on files, where
file owner ID must be equal to the user ID, except where CAP_FSETID
is applicable. It doesn't override MAC and DAC restrictions. */
Expand Down Expand Up @@ -257,7 +275,7 @@ typedef __u32 kernel_cap_t;
/* Override reserved space on ext2 filesystem */
/* Modify data journaling mode on ext3 filesystem (uses journaling
resources) */
/* NOTE: ext2 honors fsuid when checking for resource overrides, so
/* NOTE: ext2 honors fsuid when checking for resource overrides, so
you can override using fsuid too */
/* Override size restrictions on IPC message queues */
/* Allow more than 64hz interrupts from the real-time clock */
Expand Down Expand Up @@ -289,16 +307,18 @@ typedef __u32 kernel_cap_t;

#define CAP_AUDIT_CONTROL 30

#define CAP_SETFCAP 31

#ifdef __KERNEL__
/*
/*
* Bounding set
*/
extern kernel_cap_t cap_bset;

/*
* Internal kernel functions only
*/

#ifdef STRICT_CAP_T_TYPECHECKS

#define to_cap_t(x) { x }
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384

/*
* This is the Inode Attributes structure, used for notify_change(). It
Expand Down
40 changes: 36 additions & 4 deletions trunk/include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
extern void cap_task_reparent_to_init (struct task_struct *p);
extern int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid);
extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp);
extern int cap_task_setioprio (struct task_struct *p, int ioprio);
extern int cap_task_setnice (struct task_struct *p, int nice);
extern int cap_syslog (int type);
extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);

Expand Down Expand Up @@ -413,6 +419,18 @@ struct request_sock;
* is specified by @buffer_size. @buffer may be NULL to request
* the size of the buffer required.
* Returns number of bytes used/required on success.
* @inode_need_killpriv:
* Called when an inode has been changed.
* @dentry is the dentry being changed.
* Return <0 on error to abort the inode change operation.
* Return 0 if inode_killpriv does not need to be called.
* Return >0 if inode_killpriv does need to be called.
* @inode_killpriv:
* The setuid bit is being removed. Remove similar security labels.
* Called with the dentry->d_inode->i_mutex held.
* @dentry is the dentry being changed.
* Return 0 on success. If error is returned, then the operation
* causing setuid bit removal is failed.
*
* Security hooks for file operations
*
Expand Down Expand Up @@ -1239,6 +1257,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
const char *(*inode_xattr_getsuffix) (void);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
Expand Down Expand Up @@ -1496,6 +1516,8 @@ void security_inode_post_setxattr(struct dentry *dentry, char *name,
int security_inode_getxattr(struct dentry *dentry, char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
const char *security_inode_xattr_getsuffix(void);
int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
Expand Down Expand Up @@ -1891,6 +1913,16 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
return cap_inode_removexattr(dentry, name);
}

static inline int security_inode_need_killpriv(struct dentry *dentry)
{
return cap_inode_need_killpriv(dentry);
}

static inline int security_inode_killpriv(struct dentry *dentry)
{
return cap_inode_killpriv(dentry);
}

static inline const char *security_inode_xattr_getsuffix (void)
{
return NULL ;
Expand Down Expand Up @@ -2035,12 +2067,12 @@ static inline int security_task_setgroups (struct group_info *group_info)

static inline int security_task_setnice (struct task_struct *p, int nice)
{
return 0;
return cap_task_setnice(p, nice);
}

static inline int security_task_setioprio (struct task_struct *p, int ioprio)
{
return 0;
return cap_task_setioprio(p, ioprio);
}

static inline int security_task_getioprio (struct task_struct *p)
Expand All @@ -2058,7 +2090,7 @@ static inline int security_task_setscheduler (struct task_struct *p,
int policy,
struct sched_param *lp)
{
return 0;
return cap_task_setscheduler(p, policy, lp);
}

static inline int security_task_getscheduler (struct task_struct *p)
Expand All @@ -2075,7 +2107,7 @@ static inline int security_task_kill (struct task_struct *p,
struct siginfo *info, int sig,
u32 secid)
{
return 0;
return cap_task_kill(p, info, sig, secid);
}

static inline int security_task_wait (struct task_struct *p)
Expand Down
14 changes: 10 additions & 4 deletions trunk/mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1627,12 +1627,18 @@ int __remove_suid(struct dentry *dentry, int kill)

int remove_suid(struct dentry *dentry)
{
int kill = should_remove_suid(dentry);
int killsuid = should_remove_suid(dentry);
int killpriv = security_inode_need_killpriv(dentry);
int error = 0;

if (unlikely(kill))
return __remove_suid(dentry, kill);
if (killpriv < 0)
return killpriv;
if (killpriv)
error = security_inode_killpriv(dentry);
if (!error && killsuid)
error = __remove_suid(dentry, killsuid);

return 0;
return error;
}
EXPORT_SYMBOL(remove_suid);

Expand Down
10 changes: 10 additions & 0 deletions trunk/security/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ config SECURITY_CAPABILITIES
This enables the "default" Linux capabilities functionality.
If you are unsure how to answer this question, answer Y.

config SECURITY_FILE_CAPABILITIES
bool "File POSIX Capabilities (EXPERIMENTAL)"
depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
default n
help
This enables filesystem capabilities, allowing you to give
binaries a subset of root's powers without using setuid 0.

If in doubt, answer N.

config SECURITY_ROOTPLUG
bool "Root Plug Support"
depends on USB=y && SECURITY
Expand Down
6 changes: 6 additions & 0 deletions trunk/security/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ static struct security_operations capability_ops = {

.inode_setxattr = cap_inode_setxattr,
.inode_removexattr = cap_inode_removexattr,
.inode_need_killpriv = cap_inode_need_killpriv,
.inode_killpriv = cap_inode_killpriv,

.task_kill = cap_task_kill,
.task_setscheduler = cap_task_setscheduler,
.task_setioprio = cap_task_setioprio,
.task_setnice = cap_task_setnice,
.task_post_setuid = cap_task_post_setuid,
.task_reparent_to_init = cap_task_reparent_to_init,

Expand Down
Loading

0 comments on commit 229a368

Please sign in to comment.