Commit 51cfb8c4 authored by Sebastien Buisson's avatar Sebastien Buisson Committed by Greg Kroah-Hartman

staging: lustre: llite: basic support of SELinux in CLIO

Bring the ability to properly initiate security context
on SELinux-enabled client and store it on server side via
extended attribute.

Security context initialization is not atomic, but that would
require a wire protocol change to send security label in the
creation request.

Filter out security.selinux from xattr cache as it is
already cached in system slab.
Signed-off-by: default avatarSebastien Buisson <sebastien.buisson@bull.net>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5560
Reviewed-on: http://review.whamcloud.com/11648Reviewed-by: default avatarDmitry Eremin <dmitry.eremin@intel.com>
Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 96049bd1
obj-$(CONFIG_LUSTRE_FS) += lustre.o obj-$(CONFIG_LUSTRE_FS) += lustre.o
lustre-y := dcache.o dir.o file.o llite_lib.o llite_nfs.o \ lustre-y := dcache.o dir.o file.o llite_lib.o llite_nfs.o \
rw.o namei.o symlink.o llite_mmap.o range_lock.o \ rw.o rw26.o namei.o symlink.o llite_mmap.o range_lock.o \
xattr.o xattr_cache.o rw26.o super25.o statahead.o \ xattr.o xattr_cache.o xattr_security.o \
glimpse.o lcommon_cl.o lcommon_misc.o \ super25.o statahead.o glimpse.o lcommon_cl.o lcommon_misc.o \
vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \
lproc_llite.o lproc_llite.o
...@@ -410,6 +410,8 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, ...@@ -410,6 +410,8 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump,
struct ptlrpc_request *request = NULL; struct ptlrpc_request *request = NULL;
struct md_op_data *op_data; struct md_op_data *op_data;
struct ll_sb_info *sbi = ll_i2sbi(parent); struct ll_sb_info *sbi = ll_i2sbi(parent);
struct inode *inode = NULL;
struct dentry dentry;
int err; int err;
if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) if (unlikely(lump->lum_magic != LMV_USER_MAGIC))
...@@ -443,8 +445,17 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, ...@@ -443,8 +445,17 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump,
from_kgid(&init_user_ns, current_fsgid()), from_kgid(&init_user_ns, current_fsgid()),
cfs_curproc_cap_pack(), 0, &request); cfs_curproc_cap_pack(), 0, &request);
ll_finish_md_op_data(op_data); ll_finish_md_op_data(op_data);
err = ll_prep_inode(&inode, request, parent->i_sb, NULL);
if (err) if (err)
goto err_exit; goto err_exit;
memset(&dentry, 0, sizeof(dentry));
dentry.d_inode = inode;
err = ll_init_security(&dentry, inode, parent);
iput(inode);
err_exit: err_exit:
ptlrpc_req_finished(request); ptlrpc_req_finished(request);
return err; return err;
......
...@@ -261,6 +261,9 @@ int ll_xattr_cache_destroy(struct inode *inode); ...@@ -261,6 +261,9 @@ int ll_xattr_cache_destroy(struct inode *inode);
int ll_xattr_cache_get(struct inode *inode, const char *name, int ll_xattr_cache_get(struct inode *inode, const char *name,
char *buffer, size_t size, __u64 valid); char *buffer, size_t size, __u64 valid);
int ll_init_security(struct dentry *dentry, struct inode *inode,
struct inode *dir);
/* /*
* Locking to guarantee consistency of non-atomic updates to long long i_size, * Locking to guarantee consistency of non-atomic updates to long long i_size,
* consistency between file size and KMS. * consistency between file size and KMS.
...@@ -998,6 +1001,7 @@ extern const struct xattr_handler *ll_xattr_handlers[]; ...@@ -998,6 +1001,7 @@ extern const struct xattr_handler *ll_xattr_handlers[];
ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size);
int ll_xattr_list(struct inode *inode, const char *name, int type, int ll_xattr_list(struct inode *inode, const char *name, int type,
void *buffer, size_t size, __u64 valid); void *buffer, size_t size, __u64 valid);
const struct xattr_handler *get_xattr_type(const char *name);
/** /**
* Common IO arguments for various VFS I/O interfaces. * Common IO arguments for various VFS I/O interfaces.
......
...@@ -790,7 +790,8 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, ...@@ -790,7 +790,8 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry,
return PTR_ERR(inode); return PTR_ERR(inode);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
return 0;
return ll_init_security(dentry, inode, dir);
} }
void ll_update_times(struct ptlrpc_request *request, struct inode *inode) void ll_update_times(struct ptlrpc_request *request, struct inode *inode)
...@@ -885,6 +886,8 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, ...@@ -885,6 +886,8 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry,
goto err_exit; goto err_exit;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
err = ll_init_security(dentry, inode, dir);
err_exit: err_exit:
if (request) if (request)
ptlrpc_req_finished(request); ptlrpc_req_finished(request);
......
...@@ -44,48 +44,39 @@ ...@@ -44,48 +44,39 @@
#include "llite_internal.h" #include "llite_internal.h"
static const struct xattr_handler *get_xattr_type(const char *name)
int get_xattr_type(const char *name)
{ {
if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)) int i = 0;
return XATTR_ACL_ACCESS_T;
if (!strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT)) while (ll_xattr_handlers[i]) {
return XATTR_ACL_DEFAULT_T; size_t len = strlen(ll_xattr_handlers[i]->prefix);
if (!strncmp(name, XATTR_USER_PREFIX, if (!strncmp(ll_xattr_handlers[i]->prefix, name, len))
sizeof(XATTR_USER_PREFIX) - 1)) return ll_xattr_handlers[i];
return XATTR_USER_T; i++;
}
if (!strncmp(name, XATTR_TRUSTED_PREFIX, return NULL;
sizeof(XATTR_TRUSTED_PREFIX) - 1))
return XATTR_TRUSTED_T;
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1))
return XATTR_SECURITY_T;
if (!strncmp(name, XATTR_LUSTRE_PREFIX,
sizeof(XATTR_LUSTRE_PREFIX) - 1))
return XATTR_LUSTRE_T;
return XATTR_OTHER_T;
} }
static static int xattr_type_filter(struct ll_sb_info *sbi,
int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type) const struct xattr_handler *handler)
{ {
if ((xattr_type == XATTR_ACL_ACCESS_T || /* No handler means XATTR_OTHER_T */
xattr_type == XATTR_ACL_DEFAULT_T) && if (!handler)
return -EOPNOTSUPP;
if ((handler->flags == XATTR_ACL_ACCESS_T ||
handler->flags == XATTR_ACL_DEFAULT_T) &&
!(sbi->ll_flags & LL_SBI_ACL)) !(sbi->ll_flags & LL_SBI_ACL))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR)) if (handler->flags == XATTR_USER_T &&
!(sbi->ll_flags & LL_SBI_USER_XATTR))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (xattr_type == XATTR_TRUSTED_T && !capable(CFS_CAP_SYS_ADMIN))
if (handler->flags == XATTR_TRUSTED_T &&
!capable(CFS_CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (xattr_type == XATTR_OTHER_T)
return -EOPNOTSUPP;
return 0; return 0;
} }
...@@ -111,7 +102,7 @@ ll_xattr_set_common(const struct xattr_handler *handler, ...@@ -111,7 +102,7 @@ ll_xattr_set_common(const struct xattr_handler *handler,
valid = OBD_MD_FLXATTR; valid = OBD_MD_FLXATTR;
} }
rc = xattr_type_filter(sbi, handler->flags); rc = xattr_type_filter(sbi, handler);
if (rc) if (rc)
return rc; return rc;
...@@ -225,7 +216,8 @@ ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, ...@@ -225,7 +216,8 @@ ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer,
void *xdata; void *xdata;
int rc; int rc;
if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T) { if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T &&
(type != XATTR_SECURITY_T || strcmp(name, "security.selinux"))) {
rc = ll_xattr_cache_get(inode, name, buffer, size, valid); rc = ll_xattr_cache_get(inode, name, buffer, size, valid);
if (rc == -EAGAIN) if (rc == -EAGAIN)
goto getxattr_nocache; goto getxattr_nocache;
...@@ -313,7 +305,7 @@ static int ll_xattr_get_common(const struct xattr_handler *handler, ...@@ -313,7 +305,7 @@ static int ll_xattr_get_common(const struct xattr_handler *handler,
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
rc = xattr_type_filter(sbi, handler->flags); rc = xattr_type_filter(sbi, handler);
if (rc) if (rc)
return rc; return rc;
......
...@@ -415,6 +415,10 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit) ...@@ -415,6 +415,10 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
CDEBUG(D_CACHE, "not caching %s\n", CDEBUG(D_CACHE, "not caching %s\n",
XATTR_NAME_ACL_ACCESS); XATTR_NAME_ACL_ACCESS);
rc = 0; rc = 0;
} else if (!strcmp(xdata, "security.selinux")) {
/* Filter out security.selinux, it is cached in slab */
CDEBUG(D_CACHE, "not caching security.selinux\n");
rc = 0;
} else { } else {
rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval, rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval,
*xsizes); *xsizes);
......
/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is included
* in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see http://www.gnu.org/licenses
*
* GPL HEADER END
*/
/*
* Copyright (c) 2014 Bull SAS
* Author: Sebastien Buisson sebastien.buisson@bull.net
*/
/*
* lustre/llite/xattr_security.c
* Handler for storing security labels as extended attributes.
*/
#include <linux/security.h>
#include <linux/xattr.h>
#include "llite_internal.h"
/**
* A helper function for ll_security_inode_init_security()
* that takes care of setting xattrs
*
* Get security context of @inode from @xattr_array,
* and put it in 'security.xxx' xattr of dentry
* stored in @fs_info.
*
* \retval 0 success
* \retval -ENOMEM if no memory could be allocated for xattr name
* \retval < 0 failure to set xattr
*/
static int
ll_initxattrs(struct inode *inode, const struct xattr *xattr_array,
void *fs_info)
{
const struct xattr_handler *handler;
struct dentry *dentry = fs_info;
const struct xattr *xattr;
int err = 0;
handler = get_xattr_type(XATTR_SECURITY_PREFIX);
if (!handler)
return -ENXIO;
for (xattr = xattr_array; xattr->name; xattr++) {
err = handler->set(handler, dentry, inode, xattr->name,
xattr->value, xattr->value_len,
XATTR_CREATE);
if (err < 0)
break;
}
return err;
}
/**
* Initializes security context
*
* Get security context of @inode in @dir,
* and put it in 'security.xxx' xattr of @dentry.
*
* \retval 0 success, or SELinux is disabled
* \retval -ENOMEM if no memory could be allocated for xattr name
* \retval < 0 failure to get security context or set xattr
*/
int
ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir)
{
if (!selinux_is_enabled())
return 0;
return security_inode_init_security(inode, dir, NULL,
&ll_initxattrs, dentry);
}
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