Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (33 commits)
  AppArmor: kill unused macros in lsm.c
  AppArmor: cleanup generated files correctly
  KEYS: Add an iovec version of KEYCTL_INSTANTIATE
  KEYS: Add a new keyctl op to reject a key with a specified error code
  KEYS: Add a key type op to permit the key description to be vetted
  KEYS: Add an RCU payload dereference macro
  AppArmor: Cleanup make file to remove cruft and make it easier to read
  SELinux: implement the new sb_remount LSM hook
  LSM: Pass -o remount options to the LSM
  SELinux: Compute SID for the newly created socket
  SELinux: Socket retains creator role and MLS attribute
  SELinux: Auto-generate security_is_socket_class
  TOMOYO: Fix memory leak upon file open.
  Revert "selinux: simplify ioctl checking"
  selinux: drop unused packet flow permissions
  selinux: Fix packet forwarding checks on postrouting
  selinux: Fix wrong checks for selinux_policycap_netpeer
  selinux: Fix check for xfrm selinux context algorithm
  ima: remove unnecessary call to ima_must_measure
  IMA: remove IMA imbalance checking
  ...
  • Loading branch information
torvalds committed Mar 16, 2011
2 parents 0d2ecee + a002951 commit 0f6e0e8
Show file tree
Hide file tree
Showing 85 changed files with 1,549 additions and 712 deletions.
9 changes: 5 additions & 4 deletions Documentation/keys-request-key.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to
of them, and (b) it requires the same UID/GID/Groups all the way through.


======================
NEGATIVE INSTANTIATION
======================
====================================
NEGATIVE INSTANTIATION AND REJECTION
====================================

Rather than instantiating a key, it is possible for the possessor of an
authorisation key to negatively instantiate a key that's under construction.
This is a short duration placeholder that causes any attempt at re-requesting
the key whilst it exists to fail with error ENOKEY.
the key whilst it exists to fail with error ENOKEY if negated or the specified
error if rejected.

This is provided to prevent excessive repeated spawning of /sbin/request-key
processes for a key that will never be obtainable.
Expand Down
28 changes: 24 additions & 4 deletions Documentation/keys.txt
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,9 @@ The keyctl syscall functions are:
long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
const void *payload, size_t plen,
key_serial_t keyring);
long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key,
const struct iovec *payload_iov, unsigned ioc,
key_serial_t keyring);

If the kernel calls back to userspace to complete the instantiation of a
key, userspace should use this call to supply data for the key before the
Expand All @@ -652,11 +655,16 @@ The keyctl syscall functions are:

The payload and plen arguments describe the payload data as for add_key().

The payload_iov and ioc arguments describe the payload data in an iovec
array instead of a single buffer.


(*) Negatively instantiate a partially constructed key.

long keyctl(KEYCTL_NEGATE, key_serial_t key,
unsigned timeout, key_serial_t keyring);
long keyctl(KEYCTL_REJECT, key_serial_t key,
unsigned timeout, unsigned error, key_serial_t keyring);

If the kernel calls back to userspace to complete the instantiation of a
key, userspace should use this call mark the key as negative before the
Expand All @@ -669,6 +677,10 @@ The keyctl syscall functions are:
that keyring, however all the constraints applying in KEYCTL_LINK apply in
this case too.

If the key is rejected, future searches for it will return the specified
error code until the rejected key expires. Negating the key is the same
as rejecting the key with ENOKEY as the error code.


(*) Set the default request-key destination keyring.

Expand Down Expand Up @@ -1062,6 +1074,13 @@ The structure has a number of fields, some of which are mandatory:
viable.


(*) int (*vet_description)(const char *description);

This optional method is called to vet a key description. If the key type
doesn't approve of the key description, it may return an error, otherwise
it should return 0.


(*) int (*instantiate)(struct key *key, const void *data, size_t datalen);

This method is called to attach a payload to a key during construction.
Expand Down Expand Up @@ -1231,10 +1250,11 @@ hand the request off to (perhaps a path held in placed in another key by, for
example, the KDE desktop manager).

The program (or whatever it calls) should finish construction of the key by
calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
the keyrings (probably the session ring) before returning. Alternatively, the
key can be marked as negative with KEYCTL_NEGATE; this also permits the key to
be cached in one of the keyrings.
calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to
cache the key in one of the keyrings (probably the session ring) before
returning. Alternatively, the key can be marked as negative with KEYCTL_NEGATE
or KEYCTL_REJECT; this also permits the key to be cached in one of the
keyrings.

If it returns with the key remaining in the unconstructed state, the key will
be marked as being negative, it will be added to the session keyring, and an
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2130,6 +2130,11 @@ config SYSVIPC_COMPAT
def_bool y
depends on COMPAT && SYSVIPC

config KEYS_COMPAT
bool
depends on COMPAT && KEYS
default y

endmenu


Expand Down
13 changes: 7 additions & 6 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode,
unsigned long *nr_written, int unlock);

static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir)
struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;

err = btrfs_init_acl(trans, inode, dir);
if (!err)
err = btrfs_xattr_security_init(trans, inode, dir);
err = btrfs_xattr_security_init(trans, inode, dir, qstr);
return err;
}

Expand Down Expand Up @@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down Expand Up @@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down Expand Up @@ -4891,7 +4892,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

drop_on_err = 1;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_fail;

Expand Down Expand Up @@ -7103,7 +7104,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down
6 changes: 4 additions & 2 deletions fs/btrfs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,15 +370,17 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
}

int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir)
struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *suffix;
char *name;

err = security_inode_init_security(inode, dir, &suffix, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
&len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name,
extern int btrfs_removexattr(struct dentry *dentry, const char *name);

extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir);
struct inode *inode, struct inode *dir,
const struct qstr *qstr);

#endif /* __XATTR__ */
52 changes: 44 additions & 8 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
bool preemptive)
{
struct dentry *grave, *trap;
struct path path, path_to_graveyard;
char nbuffer[8 + 8 + 1];
int ret;

Expand All @@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
/* non-directories can just be unlinked */
if (!S_ISDIR(rep->d_inode->i_mode)) {
_debug("unlink stale object");
ret = vfs_unlink(dir->d_inode, rep);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);
path.mnt = cache->mnt;
path.dentry = dir;
ret = security_path_unlink(&path, rep);
if (ret < 0) {
cachefiles_io_error(cache, "Unlink security error");
} else {
ret = vfs_unlink(dir->d_inode, rep);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);
}

mutex_unlock(&dir->d_inode->i_mutex);

Expand Down Expand Up @@ -379,12 +388,23 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
}

/* attempt the rename */
ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave);
if (ret != 0 && ret != -ENOMEM)
cachefiles_io_error(cache, "Rename failed with error %d", ret);
path.mnt = cache->mnt;
path.dentry = dir;
path_to_graveyard.mnt = cache->mnt;
path_to_graveyard.dentry = cache->graveyard;
ret = security_path_rename(&path, rep, &path_to_graveyard, grave);
if (ret < 0) {
cachefiles_io_error(cache, "Rename security error %d", ret);
} else {
ret = vfs_rename(dir->d_inode, rep,
cache->graveyard->d_inode, grave);
if (ret != 0 && ret != -ENOMEM)
cachefiles_io_error(cache,
"Rename failed with error %d", ret);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);
if (preemptive)
cachefiles_mark_object_buried(cache, rep);
}

unlock_rename(cache->graveyard, dir);
dput(grave);
Expand Down Expand Up @@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
{
struct cachefiles_cache *cache;
struct dentry *dir, *next = NULL;
struct path path;
unsigned long start;
const char *name;
int ret, nlen;
Expand All @@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,

cache = container_of(parent->fscache.cache,
struct cachefiles_cache, cache);
path.mnt = cache->mnt;

ASSERT(parent->dentry);
ASSERT(parent->dentry->d_inode);
Expand Down Expand Up @@ -511,6 +533,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (ret < 0)
goto create_error;

path.dentry = dir;
ret = security_path_mkdir(&path, next, 0);
if (ret < 0)
goto create_error;
start = jiffies;
ret = vfs_mkdir(dir->d_inode, next, 0);
cachefiles_hist(cachefiles_mkdir_histogram, start);
Expand All @@ -536,6 +562,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (ret < 0)
goto create_error;

path.dentry = dir;
ret = security_path_mknod(&path, next, S_IFREG, 0);
if (ret < 0)
goto create_error;
start = jiffies;
ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
cachefiles_hist(cachefiles_create_histogram, start);
Expand Down Expand Up @@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
{
struct dentry *subdir;
unsigned long start;
struct path path;
int ret;

_enter(",,%s", dirname);
Expand Down Expand Up @@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,

_debug("attempt mkdir");

path.mnt = cache->mnt;
path.dentry = dir;
ret = security_path_mkdir(&path, subdir, 0700);
if (ret < 0)
goto mkdir_error;
ret = vfs_mkdir(dir->d_inode, subdir, 0700);
if (ret < 0)
goto mkdir_error;
Expand Down
2 changes: 1 addition & 1 deletion fs/ext2/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int);

/* ialloc.c */
extern struct inode * ext2_new_inode (struct inode *, int);
extern struct inode * ext2_new_inode (struct inode *, int, const struct qstr *);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
Expand Down
5 changes: 3 additions & 2 deletions fs/ext2/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
return group;
}

struct inode *ext2_new_inode(struct inode *dir, int mode)
struct inode *ext2_new_inode(struct inode *dir, int mode,
const struct qstr *qstr)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
Expand Down Expand Up @@ -585,7 +586,7 @@ struct inode *ext2_new_inode(struct inode *dir, int mode)
if (err)
goto fail_free_drop;

err = ext2_init_security(inode,dir);
err = ext2_init_security(inode, dir, qstr);
if (err)
goto fail_free_drop;

Expand Down
8 changes: 4 additions & 4 deletions fs/ext2/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st

dquot_initialize(dir);

inode = ext2_new_inode(dir, mode);
inode = ext2_new_inode(dir, mode, &dentry->d_name);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_

dquot_initialize(dir);

inode = ext2_new_inode (dir, mode);
inode = ext2_new_inode (dir, mode, &dentry->d_name);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, inode->i_mode, rdev);
Expand All @@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,

dquot_initialize(dir);

inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out;
Expand Down Expand Up @@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)

inode_inc_link_count(dir);

inode = ext2_new_inode (dir, S_IFDIR | mode);
inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_dir;
Expand Down
6 changes: 4 additions & 2 deletions fs/ext2/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ exit_ext2_xattr(void)
# endif /* CONFIG_EXT2_FS_XATTR */

#ifdef CONFIG_EXT2_FS_SECURITY
extern int ext2_init_security(struct inode *inode, struct inode *dir);
extern int ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr);
#else
static inline int ext2_init_security(struct inode *inode, struct inode *dir)
static inline int ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions fs/ext2/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
}

int
ext2_init_security(struct inode *inode, struct inode *dir)
ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *name;

err = security_inode_init_security(inode, dir, &name, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
Loading

0 comments on commit 0f6e0e8

Please sign in to comment.