mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
![Eric Paris](/assets/img/avatar_default.png)
SELinux would like to implement a new labeling behavior of newly created inodes. We currently label new inodes based on the parent and the creating process. This new behavior would also take into account the name of the new object when deciding the new label. This is not the (supposed) full path, just the last component of the path. This is very useful because creating /etc/shadow is different than creating /etc/passwd but the kernel hooks are unable to differentiate these operations. We currently require that userspace realize it is doing some difficult operation like that and than userspace jumps through SELinux hoops to get things set up correctly. This patch does not implement new behavior, that is obviously contained in a seperate SELinux patch, but it does pass the needed name down to the correct LSM hook. If no such name exists it is fine to pass NULL. Signed-off-by: Eric Paris <eparis@redhat.com>
120 lines
3 KiB
C
120 lines
3 KiB
C
#include <linux/reiserfs_fs.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/reiserfs_xattr.h>
|
|
#include <linux/security.h>
|
|
#include <asm/uaccess.h>
|
|
|
|
static int
|
|
security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
|
|
int handler_flags)
|
|
{
|
|
if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
|
|
return -EINVAL;
|
|
|
|
if (IS_PRIVATE(dentry->d_inode))
|
|
return -EPERM;
|
|
|
|
return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
|
|
}
|
|
|
|
static int
|
|
security_set(struct dentry *dentry, const char *name, const void *buffer,
|
|
size_t size, int flags, int handler_flags)
|
|
{
|
|
if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
|
|
return -EINVAL;
|
|
|
|
if (IS_PRIVATE(dentry->d_inode))
|
|
return -EPERM;
|
|
|
|
return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
|
|
}
|
|
|
|
static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
|
|
const char *name, size_t namelen, int handler_flags)
|
|
{
|
|
const size_t len = namelen + 1;
|
|
|
|
if (IS_PRIVATE(dentry->d_inode))
|
|
return 0;
|
|
|
|
if (list && len <= list_len) {
|
|
memcpy(list, name, namelen);
|
|
list[namelen] = '\0';
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
/* Initializes the security context for a new inode and returns the number
|
|
* of blocks needed for the transaction. If successful, reiserfs_security
|
|
* must be released using reiserfs_security_free when the caller is done. */
|
|
int reiserfs_security_init(struct inode *dir, struct inode *inode,
|
|
const struct qstr *qstr,
|
|
struct reiserfs_security_handle *sec)
|
|
{
|
|
int blocks = 0;
|
|
int error;
|
|
|
|
sec->name = NULL;
|
|
|
|
/* Don't add selinux attributes on xattrs - they'll never get used */
|
|
if (IS_PRIVATE(dir))
|
|
return 0;
|
|
|
|
error = security_inode_init_security(inode, dir, qstr, &sec->name,
|
|
&sec->value, &sec->length);
|
|
if (error) {
|
|
if (error == -EOPNOTSUPP)
|
|
error = 0;
|
|
|
|
sec->name = NULL;
|
|
sec->value = NULL;
|
|
sec->length = 0;
|
|
return error;
|
|
}
|
|
|
|
if (sec->length && reiserfs_xattrs_initialized(inode->i_sb)) {
|
|
blocks = reiserfs_xattr_jcreate_nblocks(inode) +
|
|
reiserfs_xattr_nblocks(inode, sec->length);
|
|
/* We don't want to count the directories twice if we have
|
|
* a default ACL. */
|
|
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
|
|
}
|
|
return blocks;
|
|
}
|
|
|
|
int reiserfs_security_write(struct reiserfs_transaction_handle *th,
|
|
struct inode *inode,
|
|
struct reiserfs_security_handle *sec)
|
|
{
|
|
int error;
|
|
if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
|
|
return -EINVAL;
|
|
|
|
error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
|
|
sec->length, XATTR_CREATE);
|
|
if (error == -ENODATA || error == -EOPNOTSUPP)
|
|
error = 0;
|
|
|
|
return error;
|
|
}
|
|
|
|
void reiserfs_security_free(struct reiserfs_security_handle *sec)
|
|
{
|
|
kfree(sec->name);
|
|
kfree(sec->value);
|
|
sec->name = NULL;
|
|
sec->value = NULL;
|
|
}
|
|
|
|
const struct xattr_handler reiserfs_xattr_security_handler = {
|
|
.prefix = XATTR_SECURITY_PREFIX,
|
|
.get = security_get,
|
|
.set = security_set,
|
|
.list = security_list,
|
|
};
|