Merge 7c7fdaf6ad ("Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt") into android-mainline
Steps on the way to 5.11-rc1. The fscrypt merge, which, in amazement, merges cleanly! Cc: Eric Biggers <ebiggers@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I61bcf8c63a42011881a12eb41339c0c239b1cdc8
This commit is contained in:
@@ -404,7 +404,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
|
||||
fname->disk_name.len = iname->len;
|
||||
return 0;
|
||||
}
|
||||
ret = fscrypt_get_encryption_info(dir);
|
||||
ret = fscrypt_get_encryption_info(dir, lookup);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -560,7 +560,11 @@ int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
return -ECHILD;
|
||||
|
||||
dir = dget_parent(dentry);
|
||||
err = fscrypt_get_encryption_info(d_inode(dir));
|
||||
/*
|
||||
* Pass allow_unsupported=true, so that files with an unsupported
|
||||
* encryption policy can be deleted.
|
||||
*/
|
||||
err = fscrypt_get_encryption_info(d_inode(dir), true);
|
||||
valid = !fscrypt_has_encryption_key(d_inode(dir));
|
||||
dput(dir);
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#define FSCRYPT_CONTEXT_V1 1
|
||||
#define FSCRYPT_CONTEXT_V2 2
|
||||
|
||||
/* Keep this in sync with include/uapi/linux/fscrypt.h */
|
||||
#define FSCRYPT_MODE_MAX FSCRYPT_MODE_ADIANTUM
|
||||
|
||||
struct fscrypt_context_v1 {
|
||||
u8 version; /* FSCRYPT_CONTEXT_V1 */
|
||||
u8 contents_encryption_mode;
|
||||
@@ -466,16 +469,9 @@ struct fscrypt_master_key {
|
||||
* FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
|
||||
* FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
|
||||
*
|
||||
* Locking: protected by key->sem (outer) and mk_secret_sem (inner).
|
||||
* The reason for two locks is that key->sem also protects modifying
|
||||
* mk_users, which ranks it above the semaphore for the keyring key
|
||||
* type, which is in turn above page faults (via keyring_read). But
|
||||
* sometimes filesystems call fscrypt_get_encryption_info() from within
|
||||
* a transaction, which ranks it below page faults. So we need a
|
||||
* separate lock which protects mk_secret but not also mk_users.
|
||||
* Locking: protected by this master key's key->sem.
|
||||
*/
|
||||
struct fscrypt_master_key_secret mk_secret;
|
||||
struct rw_semaphore mk_secret_sem;
|
||||
|
||||
/*
|
||||
* For v1 policy keys: an arbitrary key descriptor which was assigned by
|
||||
@@ -494,8 +490,8 @@ struct fscrypt_master_key {
|
||||
*
|
||||
* This is NULL for v1 policy keys; those can only be added by root.
|
||||
*
|
||||
* Locking: in addition to this keyrings own semaphore, this is
|
||||
* protected by the master key's key->sem, so we can do atomic
|
||||
* Locking: in addition to this keyring's own semaphore, this is
|
||||
* protected by this master key's key->sem, so we can do atomic
|
||||
* search+insert. It can also be searched without taking any locks, but
|
||||
* in that case the returned key may have already been removed.
|
||||
*/
|
||||
@@ -521,9 +517,9 @@ struct fscrypt_master_key {
|
||||
* Per-mode encryption keys for the various types of encryption policies
|
||||
* that use them. Allocated and derived on-demand.
|
||||
*/
|
||||
struct fscrypt_prepared_key mk_direct_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
struct fscrypt_prepared_key mk_direct_keys[FSCRYPT_MODE_MAX + 1];
|
||||
struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[FSCRYPT_MODE_MAX + 1];
|
||||
struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[FSCRYPT_MODE_MAX + 1];
|
||||
|
||||
/* Hash key for inode numbers. Initialized only when needed. */
|
||||
siphash_key_t mk_ino_hash_key;
|
||||
@@ -537,9 +533,9 @@ is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
|
||||
/*
|
||||
* The READ_ONCE() is only necessary for fscrypt_drop_inode() and
|
||||
* fscrypt_key_describe(). These run in atomic context, so they can't
|
||||
* take ->mk_secret_sem and thus 'secret' can change concurrently which
|
||||
* would be a data race. But they only need to know whether the secret
|
||||
* *was* present at the time of check, so READ_ONCE() suffices.
|
||||
* take the key semaphore and thus 'secret' can change concurrently
|
||||
* which would be a data race. But they only need to know whether the
|
||||
* secret *was* present at the time of check, so READ_ONCE() suffices.
|
||||
*/
|
||||
return READ_ONCE(secret->size) != 0;
|
||||
}
|
||||
@@ -606,6 +602,34 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
|
||||
const struct fscrypt_master_key *mk);
|
||||
|
||||
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported);
|
||||
|
||||
/**
|
||||
* fscrypt_require_key() - require an inode's encryption key
|
||||
* @inode: the inode we need the key for
|
||||
*
|
||||
* If the inode is encrypted, set up its encryption key if not already done.
|
||||
* Then require that the key be present and return -ENOKEY otherwise.
|
||||
*
|
||||
* No locks are needed, and the key will live as long as the struct inode --- so
|
||||
* it won't go away from under you.
|
||||
*
|
||||
* Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
|
||||
* if a problem occurred while setting up the encryption key.
|
||||
*/
|
||||
static inline int fscrypt_require_key(struct inode *inode)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
int err = fscrypt_get_encryption_info(inode, false);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
if (!fscrypt_has_encryption_key(inode))
|
||||
return -ENOKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keysetup_v1.c */
|
||||
|
||||
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
|
||||
|
||||
@@ -54,15 +54,12 @@ EXPORT_SYMBOL_GPL(fscrypt_file_open);
|
||||
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = fscrypt_require_key(dir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* ... in case we looked up no-key name before key was added */
|
||||
if (dentry->d_flags & DCACHE_NOKEY_NAME)
|
||||
if (fscrypt_is_nokey_name(dentry))
|
||||
return -ENOKEY;
|
||||
/*
|
||||
* We don't need to separately check that the directory inode's key is
|
||||
* available, as it's implied by the dentry not being a no-key name.
|
||||
*/
|
||||
|
||||
if (!fscrypt_has_permitted_context(dir, inode))
|
||||
return -EXDEV;
|
||||
@@ -75,19 +72,13 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = fscrypt_require_key(old_dir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fscrypt_require_key(new_dir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* ... in case we looked up no-key name(s) before key was added */
|
||||
if ((old_dentry->d_flags | new_dentry->d_flags) & DCACHE_NOKEY_NAME)
|
||||
if (fscrypt_is_nokey_name(old_dentry) ||
|
||||
fscrypt_is_nokey_name(new_dentry))
|
||||
return -ENOKEY;
|
||||
/*
|
||||
* We don't need to separately check that the directory inodes' keys are
|
||||
* available, as it's implied by the dentries not being no-key names.
|
||||
*/
|
||||
|
||||
if (old_dir != new_dir) {
|
||||
if (IS_ENCRYPTED(new_dir) &&
|
||||
@@ -122,6 +113,20 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
|
||||
|
||||
int __fscrypt_prepare_readdir(struct inode *dir)
|
||||
{
|
||||
return fscrypt_get_encryption_info(dir, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_readdir);
|
||||
|
||||
int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
{
|
||||
if (attr->ia_valid & ATTR_SIZE)
|
||||
return fscrypt_require_key(d_inode(dentry));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_setattr);
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_setflags() - prepare to change flags with FS_IOC_SETFLAGS
|
||||
* @inode: the inode on which flags are being changed
|
||||
@@ -137,6 +142,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
|
||||
unsigned int oldflags, unsigned int flags)
|
||||
{
|
||||
struct fscrypt_info *ci;
|
||||
struct key *key;
|
||||
struct fscrypt_master_key *mk;
|
||||
int err;
|
||||
|
||||
@@ -152,13 +158,14 @@ int fscrypt_prepare_setflags(struct inode *inode,
|
||||
ci = inode->i_crypt_info;
|
||||
if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
|
||||
return -EINVAL;
|
||||
mk = ci->ci_master_key->payload.data[0];
|
||||
down_read(&mk->mk_secret_sem);
|
||||
key = ci->ci_master_key;
|
||||
mk = key->payload.data[0];
|
||||
down_read(&key->sem);
|
||||
if (is_master_key_secret_present(&mk->mk_secret))
|
||||
err = fscrypt_derive_dirhash_key(ci, mk);
|
||||
else
|
||||
err = -ENOKEY;
|
||||
up_read(&mk->mk_secret_sem);
|
||||
up_read(&key->sem);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
@@ -324,7 +331,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
* Try to set up the symlink's encryption key, but we can continue
|
||||
* regardless of whether the key is available or not.
|
||||
*/
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
err = fscrypt_get_encryption_info(inode, false);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
has_key = fscrypt_has_encryption_key(inode);
|
||||
|
||||
@@ -44,7 +44,7 @@ static void free_master_key(struct fscrypt_master_key *mk)
|
||||
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
|
||||
for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) {
|
||||
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
|
||||
fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
|
||||
fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
|
||||
fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
|
||||
@@ -347,7 +347,6 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
|
||||
mk->mk_spec = *mk_spec;
|
||||
|
||||
move_master_key_secret(&mk->mk_secret, secret);
|
||||
init_rwsem(&mk->mk_secret_sem);
|
||||
|
||||
refcount_set(&mk->mk_refcount, 1); /* secret is present */
|
||||
INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
|
||||
@@ -427,11 +426,8 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
|
||||
}
|
||||
|
||||
/* Re-add the secret if needed. */
|
||||
if (rekey) {
|
||||
down_write(&mk->mk_secret_sem);
|
||||
if (rekey)
|
||||
move_master_key_secret(&mk->mk_secret, secret);
|
||||
up_write(&mk->mk_secret_sem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1005,10 +1001,8 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
|
||||
/* No user claims remaining. Go ahead and wipe the secret. */
|
||||
dead = false;
|
||||
if (is_master_key_secret_present(&mk->mk_secret)) {
|
||||
down_write(&mk->mk_secret_sem);
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
dead = refcount_dec_and_test(&mk->mk_refcount);
|
||||
up_write(&mk->mk_secret_sem);
|
||||
}
|
||||
up_write(&key->sem);
|
||||
if (dead) {
|
||||
|
||||
@@ -56,6 +56,8 @@ static struct fscrypt_mode *
|
||||
select_encryption_mode(const union fscrypt_policy *policy,
|
||||
const struct inode *inode)
|
||||
{
|
||||
BUILD_BUG_ON(ARRAY_SIZE(fscrypt_modes) != FSCRYPT_MODE_MAX + 1);
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
return &fscrypt_modes[fscrypt_policy_contents_mode(policy)];
|
||||
|
||||
@@ -175,7 +177,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
||||
unsigned int hkdf_infolen = 0;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX))
|
||||
if (WARN_ON(mode_num > FSCRYPT_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
prep_key = &keys[mode_num];
|
||||
@@ -374,11 +376,11 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
||||
* Find the master key, then set up the inode's actual encryption key.
|
||||
*
|
||||
* If the master key is found in the filesystem-level keyring, then the
|
||||
* corresponding 'struct key' is returned in *master_key_ret with
|
||||
* ->mk_secret_sem read-locked. This is needed to ensure that only one task
|
||||
* links the fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race
|
||||
* to create an fscrypt_info for the same inode), and to synchronize the master
|
||||
* key being removed with a new inode starting to use it.
|
||||
* corresponding 'struct key' is returned in *master_key_ret with its semaphore
|
||||
* read-locked. This is needed to ensure that only one task links the
|
||||
* fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
|
||||
* an fscrypt_info for the same inode), and to synchronize the master key being
|
||||
* removed with a new inode starting to use it.
|
||||
*/
|
||||
static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
bool need_dirhash_key,
|
||||
@@ -427,7 +429,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
}
|
||||
|
||||
mk = key->payload.data[0];
|
||||
down_read(&mk->mk_secret_sem);
|
||||
down_read(&key->sem);
|
||||
|
||||
/* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
|
||||
if (!is_master_key_secret_present(&mk->mk_secret)) {
|
||||
@@ -474,7 +476,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
return 0;
|
||||
|
||||
out_release_key:
|
||||
up_read(&mk->mk_secret_sem);
|
||||
up_read(&key->sem);
|
||||
key_put(key);
|
||||
return err;
|
||||
}
|
||||
@@ -577,9 +579,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
res = 0;
|
||||
out:
|
||||
if (master_key) {
|
||||
struct fscrypt_master_key *mk = master_key->payload.data[0];
|
||||
|
||||
up_read(&mk->mk_secret_sem);
|
||||
up_read(&master_key->sem);
|
||||
key_put(master_key);
|
||||
}
|
||||
put_crypt_info(crypt_info);
|
||||
@@ -589,6 +589,11 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
/**
|
||||
* fscrypt_get_encryption_info() - set up an inode's encryption key
|
||||
* @inode: the inode to set up the key for. Must be encrypted.
|
||||
* @allow_unsupported: if %true, treat an unsupported encryption policy (or
|
||||
* unrecognized encryption context) the same way as the key
|
||||
* being unavailable, instead of returning an error. Use
|
||||
* %false unless the operation being performed is needed in
|
||||
* order for files (or directories) to be deleted.
|
||||
*
|
||||
* Set up ->i_crypt_info, if it hasn't already been done.
|
||||
*
|
||||
@@ -599,7 +604,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
* encryption key is unavailable. (Use fscrypt_has_encryption_key() to
|
||||
* distinguish these cases.) Also can return another -errno code.
|
||||
*/
|
||||
int fscrypt_get_encryption_info(struct inode *inode)
|
||||
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
|
||||
{
|
||||
int res;
|
||||
union fscrypt_context ctx;
|
||||
@@ -610,29 +615,38 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
||||
|
||||
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
|
||||
if (res < 0) {
|
||||
if (res == -ERANGE && allow_unsupported)
|
||||
return 0;
|
||||
fscrypt_warn(inode, "Error %d getting encryption context", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = fscrypt_policy_from_context(&policy, &ctx, res);
|
||||
if (res) {
|
||||
if (allow_unsupported)
|
||||
return 0;
|
||||
fscrypt_warn(inode,
|
||||
"Unrecognized or corrupt encryption context");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!fscrypt_supported_policy(&policy, inode))
|
||||
if (!fscrypt_supported_policy(&policy, inode)) {
|
||||
if (allow_unsupported)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = fscrypt_setup_encryption_info(inode, &policy,
|
||||
fscrypt_context_nonce(&ctx),
|
||||
IS_CASEFOLDED(inode) &&
|
||||
S_ISDIR(inode->i_mode));
|
||||
|
||||
if (res == -ENOPKG && allow_unsupported) /* Algorithm unavailable? */
|
||||
res = 0;
|
||||
if (res == -ENOKEY)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_get_encryption_info);
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_new_inode() - prepare to create a new inode in a directory
|
||||
@@ -753,7 +767,7 @@ int fscrypt_drop_inode(struct inode *inode)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Note: since we aren't holding ->mk_secret_sem, the result here can
|
||||
* Note: since we aren't holding the key semaphore, the result here can
|
||||
* immediately become outdated. But there's no correctness problem with
|
||||
* unnecessarily evicting. Nor is there a correctness problem with not
|
||||
* evicting while iput() is racing with the key being removed, since
|
||||
|
||||
@@ -175,7 +175,10 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) {
|
||||
if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK |
|
||||
FSCRYPT_POLICY_FLAG_DIRECT_KEY |
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 |
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
|
||||
fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)",
|
||||
policy->flags);
|
||||
return false;
|
||||
@@ -587,7 +590,7 @@ EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce);
|
||||
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
|
||||
{
|
||||
union fscrypt_policy parent_policy, child_policy;
|
||||
int err;
|
||||
int err, err1, err2;
|
||||
|
||||
/* No restrictions on file types which are never encrypted */
|
||||
if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
|
||||
@@ -617,19 +620,25 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
|
||||
* In any case, if an unexpected error occurs, fall back to "forbidden".
|
||||
*/
|
||||
|
||||
err = fscrypt_get_encryption_info(parent);
|
||||
err = fscrypt_get_encryption_info(parent, true);
|
||||
if (err)
|
||||
return 0;
|
||||
err = fscrypt_get_encryption_info(child);
|
||||
err = fscrypt_get_encryption_info(child, true);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
err = fscrypt_get_policy(parent, &parent_policy);
|
||||
if (err)
|
||||
return 0;
|
||||
err1 = fscrypt_get_policy(parent, &parent_policy);
|
||||
err2 = fscrypt_get_policy(child, &child_policy);
|
||||
|
||||
err = fscrypt_get_policy(child, &child_policy);
|
||||
if (err)
|
||||
/*
|
||||
* Allow the case where the parent and child both have an unrecognized
|
||||
* encryption policy, so that files with an unrecognized encryption
|
||||
* policy can be deleted.
|
||||
*/
|
||||
if (err1 == -EINVAL && err2 == -EINVAL)
|
||||
return 1;
|
||||
|
||||
if (err1 || err2)
|
||||
return 0;
|
||||
|
||||
return fscrypt_policies_equal(&parent_policy, &child_policy);
|
||||
|
||||
@@ -139,11 +139,9 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
struct buffer_head *bh = NULL;
|
||||
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
|
||||
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = fscrypt_prepare_readdir(inode);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (is_dx_dir(inode)) {
|
||||
err = ext4_dx_readdir(file, ctx);
|
||||
@@ -640,13 +638,6 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ext4_dir_open(struct inode * inode, struct file * filp)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ext4_release_dir(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (filp->private_data)
|
||||
@@ -688,6 +679,5 @@ const struct file_operations ext4_dir_operations = {
|
||||
.compat_ioctl = ext4_compat_ioctl,
|
||||
#endif
|
||||
.fsync = ext4_sync_file,
|
||||
.open = ext4_dir_open,
|
||||
.release = ext4_release_dir,
|
||||
};
|
||||
|
||||
@@ -647,13 +647,7 @@ static struct stats dx_show_leaf(struct inode *dir,
|
||||
|
||||
name = de->name;
|
||||
len = de->name_len;
|
||||
if (IS_ENCRYPTED(dir))
|
||||
res = fscrypt_get_encryption_info(dir);
|
||||
if (res) {
|
||||
printk(KERN_WARNING "Error setting up"
|
||||
" fname crypto: %d\n", res);
|
||||
}
|
||||
if (!fscrypt_has_encryption_key(dir)) {
|
||||
if (!IS_ENCRYPTED(dir)) {
|
||||
/* Directory is not encrypted */
|
||||
ext4fs_dirhash(dir, de->name,
|
||||
de->name_len, &h);
|
||||
@@ -1036,7 +1030,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
||||
csum ? NULL : dir));
|
||||
/* Check if the directory is encrypted */
|
||||
if (IS_ENCRYPTED(dir)) {
|
||||
err = fscrypt_get_encryption_info(dir);
|
||||
err = fscrypt_prepare_readdir(dir);
|
||||
if (err < 0) {
|
||||
brelse(bh);
|
||||
return err;
|
||||
@@ -2302,6 +2296,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
if (!dentry->d_name.len)
|
||||
return -EINVAL;
|
||||
|
||||
if (fscrypt_is_nokey_name(dentry))
|
||||
return -ENOKEY;
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) &&
|
||||
sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name))
|
||||
|
||||
@@ -1076,7 +1076,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
|
||||
int err = 0;
|
||||
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
err = fscrypt_prepare_readdir(inode);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -1135,19 +1135,11 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
|
||||
return err < 0 ? err : 0;
|
||||
}
|
||||
|
||||
static int f2fs_dir_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct file_operations f2fs_dir_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.iterate_shared = f2fs_readdir,
|
||||
.fsync = f2fs_sync_file,
|
||||
.open = f2fs_dir_open,
|
||||
.unlocked_ioctl = f2fs_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = f2fs_compat_ioctl,
|
||||
|
||||
@@ -3254,6 +3254,8 @@ bool f2fs_empty_dir(struct inode *dir);
|
||||
|
||||
static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
|
||||
{
|
||||
if (fscrypt_is_nokey_name(dentry))
|
||||
return -ENOKEY;
|
||||
return f2fs_do_add_link(d_inode(dentry->d_parent), &dentry->d_name,
|
||||
inode, inode->i_ino, inode->i_mode);
|
||||
}
|
||||
|
||||
@@ -271,6 +271,15 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
return d_splice_alias(inode, dentry);
|
||||
}
|
||||
|
||||
static int ubifs_prepare_create(struct inode *dir, struct dentry *dentry,
|
||||
struct fscrypt_name *nm)
|
||||
{
|
||||
if (fscrypt_is_nokey_name(dentry))
|
||||
return -ENOKEY;
|
||||
|
||||
return fscrypt_setup_filename(dir, &dentry->d_name, 0, nm);
|
||||
}
|
||||
|
||||
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
bool excl)
|
||||
{
|
||||
@@ -294,7 +303,7 @@ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
|
||||
err = ubifs_prepare_create(dir, dentry, &nm);
|
||||
if (err)
|
||||
goto out_budg;
|
||||
|
||||
@@ -506,7 +515,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
|
||||
return 0;
|
||||
|
||||
if (encrypted) {
|
||||
err = fscrypt_get_encryption_info(dir);
|
||||
err = fscrypt_prepare_readdir(dir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -954,7 +963,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
|
||||
err = ubifs_prepare_create(dir, dentry, &nm);
|
||||
if (err)
|
||||
goto out_budg;
|
||||
|
||||
@@ -1039,7 +1048,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
|
||||
err = ubifs_prepare_create(dir, dentry, &nm);
|
||||
if (err) {
|
||||
kfree(dev);
|
||||
goto out_budg;
|
||||
@@ -1123,7 +1132,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
|
||||
err = ubifs_prepare_create(dir, dentry, &nm);
|
||||
if (err)
|
||||
goto out_budg;
|
||||
|
||||
@@ -1611,14 +1620,6 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ubifs_dir_open(struct inode *dir, struct file *file)
|
||||
{
|
||||
if (IS_ENCRYPTED(dir))
|
||||
return fscrypt_get_encryption_info(dir) ? -EACCES : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct inode_operations ubifs_dir_inode_operations = {
|
||||
.lookup = ubifs_lookup,
|
||||
.create = ubifs_create,
|
||||
@@ -1645,7 +1646,6 @@ const struct file_operations ubifs_dir_operations = {
|
||||
.iterate_shared = ubifs_readdir,
|
||||
.fsync = ubifs_fsync,
|
||||
.unlocked_ioctl = ubifs_ioctl,
|
||||
.open = ubifs_dir_open,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ubifs_compat_ioctl,
|
||||
#endif
|
||||
|
||||
@@ -75,7 +75,7 @@ struct fscrypt_operations {
|
||||
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
|
||||
{
|
||||
/*
|
||||
* Pairs with the cmpxchg_release() in fscrypt_get_encryption_info().
|
||||
* Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
|
||||
* I.e., another task may publish ->i_crypt_info concurrently, executing
|
||||
* a RELEASE barrier. We need to use smp_load_acquire() here to safely
|
||||
* ACQUIRE the memory the other task published.
|
||||
@@ -111,6 +111,35 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
||||
dentry->d_flags &= ~DCACHE_NOKEY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_is_nokey_name() - test whether a dentry is a no-key name
|
||||
* @dentry: the dentry to check
|
||||
*
|
||||
* This returns true if the dentry is a no-key dentry. A no-key dentry is a
|
||||
* dentry that was created in an encrypted directory that hasn't had its
|
||||
* encryption key added yet. Such dentries may be either positive or negative.
|
||||
*
|
||||
* When a filesystem is asked to create a new filename in an encrypted directory
|
||||
* and the new filename's dentry is a no-key dentry, it must fail the operation
|
||||
* with ENOKEY. This includes ->create(), ->mkdir(), ->mknod(), ->symlink(),
|
||||
* ->rename(), and ->link(). (However, ->rename() and ->link() are already
|
||||
* handled by fscrypt_prepare_rename() and fscrypt_prepare_link().)
|
||||
*
|
||||
* This is necessary because creating a filename requires the directory's
|
||||
* encryption key, but just checking for the key on the directory inode during
|
||||
* the final filesystem operation doesn't guarantee that the key was available
|
||||
* during the preceding dentry lookup. And the key must have already been
|
||||
* available during the dentry lookup in order for it to have been checked
|
||||
* whether the filename already exists in the directory and for the new file's
|
||||
* dentry not to be invalidated due to it incorrectly having the no-key flag.
|
||||
*
|
||||
* Return: %true if the dentry is a no-key name
|
||||
*/
|
||||
static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
||||
{
|
||||
return dentry->d_flags & DCACHE_NOKEY_NAME;
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||
|
||||
@@ -171,7 +200,6 @@ int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
|
||||
|
||||
/* keysetup.c */
|
||||
int fscrypt_get_encryption_info(struct inode *inode);
|
||||
int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
|
||||
bool *encrypt_ret);
|
||||
void fscrypt_put_encryption_info(struct inode *inode);
|
||||
@@ -213,6 +241,8 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
unsigned int flags);
|
||||
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct fscrypt_name *fname);
|
||||
int __fscrypt_prepare_readdir(struct inode *dir);
|
||||
int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int fscrypt_prepare_setflags(struct inode *inode,
|
||||
unsigned int oldflags, unsigned int flags);
|
||||
int fscrypt_prepare_symlink(struct inode *dir, const char *target,
|
||||
@@ -244,6 +274,11 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
||||
{
|
||||
@@ -372,10 +407,6 @@ static inline int fscrypt_ioctl_get_key_status(struct file *filp,
|
||||
}
|
||||
|
||||
/* keysetup.c */
|
||||
static inline int fscrypt_get_encryption_info(struct inode *inode)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_prepare_new_inode(struct inode *dir,
|
||||
struct inode *inode,
|
||||
@@ -503,6 +534,17 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_readdir(struct inode *dir)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_setattr(struct dentry *dentry,
|
||||
struct iattr *attr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_prepare_setflags(struct inode *inode,
|
||||
unsigned int oldflags,
|
||||
unsigned int flags)
|
||||
@@ -674,32 +716,6 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
return fscrypt_get_info(inode) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_require_key() - require an inode's encryption key
|
||||
* @inode: the inode we need the key for
|
||||
*
|
||||
* If the inode is encrypted, set up its encryption key if not already done.
|
||||
* Then require that the key be present and return -ENOKEY otherwise.
|
||||
*
|
||||
* No locks are needed, and the key will live as long as the struct inode --- so
|
||||
* it won't go away from under you.
|
||||
*
|
||||
* Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
|
||||
* if a problem occurred while setting up the encryption key.
|
||||
*/
|
||||
static inline int fscrypt_require_key(struct inode *inode)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
int err = fscrypt_get_encryption_info(inode);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
if (!fscrypt_has_encryption_key(inode))
|
||||
return -ENOKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_link() - prepare to link an inode into a possibly-encrypted
|
||||
* directory
|
||||
@@ -709,8 +725,7 @@ static inline int fscrypt_require_key(struct inode *inode)
|
||||
*
|
||||
* A new link can only be added to an encrypted directory if the directory's
|
||||
* encryption key is available --- since otherwise we'd have no way to encrypt
|
||||
* the filename. Therefore, we first set up the directory's encryption key (if
|
||||
* not already done) and return an error if it's unavailable.
|
||||
* the filename.
|
||||
*
|
||||
* We also verify that the link will not violate the constraint that all files
|
||||
* in an encrypted directory tree use the same encryption policy.
|
||||
@@ -771,8 +786,9 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir,
|
||||
*
|
||||
* Prepare for ->lookup() in a directory which may be encrypted by determining
|
||||
* the name that will actually be used to search the directory on-disk. If the
|
||||
* directory's encryption key is available, then the lookup is assumed to be by
|
||||
* plaintext name; otherwise, it is assumed to be by no-key name.
|
||||
* directory's encryption policy is supported by this kernel and its encryption
|
||||
* key is available, then the lookup is assumed to be by plaintext name;
|
||||
* otherwise, it is assumed to be by no-key name.
|
||||
*
|
||||
* This will set DCACHE_NOKEY_NAME on the dentry if the lookup is by no-key
|
||||
* name. In this case the filesystem must assign the dentry a dentry_operations
|
||||
@@ -798,6 +814,26 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_readdir() - prepare to read a possibly-encrypted directory
|
||||
* @dir: the directory inode
|
||||
*
|
||||
* If the directory is encrypted and it doesn't already have its encryption key
|
||||
* set up, try to set it up so that the filenames will be listed in plaintext
|
||||
* form rather than in no-key form.
|
||||
*
|
||||
* Return: 0 on success; -errno on error. Note that the encryption key being
|
||||
* unavailable is not considered an error. It is also not an error if
|
||||
* the encryption policy is unsupported by this kernel; that is treated
|
||||
* like the key being unavailable, so that files can still be deleted.
|
||||
*/
|
||||
static inline int fscrypt_prepare_readdir(struct inode *dir)
|
||||
{
|
||||
if (IS_ENCRYPTED(dir))
|
||||
return __fscrypt_prepare_readdir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_setattr() - prepare to change a possibly-encrypted inode's
|
||||
* attributes
|
||||
@@ -819,8 +855,8 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
|
||||
static inline int fscrypt_prepare_setattr(struct dentry *dentry,
|
||||
struct iattr *attr)
|
||||
{
|
||||
if (attr->ia_valid & ATTR_SIZE)
|
||||
return fscrypt_require_key(d_inode(dentry));
|
||||
if (IS_ENCRYPTED(d_inode(dentry)))
|
||||
return __fscrypt_prepare_setattr(dentry, attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
|
||||
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08
|
||||
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 0x10
|
||||
#define FSCRYPT_POLICY_FLAGS_VALID 0x1F
|
||||
|
||||
/* Encryption algorithms */
|
||||
#define FSCRYPT_MODE_AES_256_XTS 1
|
||||
@@ -28,7 +27,7 @@
|
||||
#define FSCRYPT_MODE_AES_128_CBC 5
|
||||
#define FSCRYPT_MODE_AES_128_CTS 6
|
||||
#define FSCRYPT_MODE_ADIANTUM 9
|
||||
#define __FSCRYPT_MODE_MAX 9
|
||||
/* If adding a mode number > 9, update FSCRYPT_MODE_MAX in fscrypt_private.h */
|
||||
|
||||
/*
|
||||
* Legacy policy version; ad-hoc KDF and no key verification.
|
||||
@@ -180,7 +179,7 @@ struct fscrypt_get_key_status_arg {
|
||||
#define FS_POLICY_FLAGS_PAD_32 FSCRYPT_POLICY_FLAGS_PAD_32
|
||||
#define FS_POLICY_FLAGS_PAD_MASK FSCRYPT_POLICY_FLAGS_PAD_MASK
|
||||
#define FS_POLICY_FLAG_DIRECT_KEY FSCRYPT_POLICY_FLAG_DIRECT_KEY
|
||||
#define FS_POLICY_FLAGS_VALID FSCRYPT_POLICY_FLAGS_VALID
|
||||
#define FS_POLICY_FLAGS_VALID 0x07 /* contains old flags only */
|
||||
#define FS_ENCRYPTION_MODE_INVALID 0 /* never used */
|
||||
#define FS_ENCRYPTION_MODE_AES_256_XTS FSCRYPT_MODE_AES_256_XTS
|
||||
#define FS_ENCRYPTION_MODE_AES_256_GCM 2 /* never used */
|
||||
|
||||
@@ -311,7 +311,7 @@ static LIST_HEAD(tomoyo_log);
|
||||
/* Lock for "struct list_head tomoyo_log". */
|
||||
static DEFINE_SPINLOCK(tomoyo_log_lock);
|
||||
|
||||
/* Length of "stuct list_head tomoyo_log". */
|
||||
/* Length of "struct list_head tomoyo_log". */
|
||||
static unsigned int tomoyo_log_count;
|
||||
|
||||
/**
|
||||
|
||||
@@ -498,7 +498,7 @@ static struct tomoyo_profile *tomoyo_assign_profile
|
||||
ptr = ns->profile_ptr[profile];
|
||||
if (ptr)
|
||||
return ptr;
|
||||
entry = kzalloc(sizeof(*entry), GFP_NOFS);
|
||||
entry = kzalloc(sizeof(*entry), GFP_NOFS | __GFP_NOWARN);
|
||||
if (mutex_lock_interruptible(&tomoyo_policy_lock))
|
||||
goto out;
|
||||
ptr = ns->profile_ptr[profile];
|
||||
@@ -635,7 +635,7 @@ static int tomoyo_set_mode(char *name, const char *value,
|
||||
if (strstr(value, tomoyo_mode[mode]))
|
||||
/*
|
||||
* Update lower 3 bits in order to distinguish
|
||||
* 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
|
||||
* 'config' from 'TOMOYO_CONFIG_USE_DEFAULT'.
|
||||
*/
|
||||
config = (config & ~7) | mode;
|
||||
if (config != TOMOYO_CONFIG_USE_DEFAULT) {
|
||||
@@ -2574,7 +2574,7 @@ static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head)
|
||||
* tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
|
||||
*
|
||||
* @head: Pointer to "struct tomoyo_io_buffer".
|
||||
* @buffer: Poiner to buffer to write to.
|
||||
* @buffer: Pointer to buffer to write to.
|
||||
* @buffer_len: Size of @buffer.
|
||||
*
|
||||
* Returns bytes read on success, negative value otherwise.
|
||||
@@ -2608,7 +2608,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
|
||||
/**
|
||||
* tomoyo_parse_policy - Parse a policy line.
|
||||
*
|
||||
* @head: Poiter to "struct tomoyo_io_buffer".
|
||||
* @head: Pointer to "struct tomoyo_io_buffer".
|
||||
* @line: Line to parse.
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
|
||||
@@ -98,7 +98,7 @@ static bool tomoyo_envp(const char *env_name, const char *env_value,
|
||||
* @argc: Length of @argc.
|
||||
* @argv: Pointer to "struct tomoyo_argv".
|
||||
* @envc: Length of @envp.
|
||||
* @envp: Poiner to "struct tomoyo_envp".
|
||||
* @envp: Pointer to "struct tomoyo_envp".
|
||||
*
|
||||
* Returns true on success, false otherwise.
|
||||
*/
|
||||
|
||||
@@ -473,9 +473,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname)
|
||||
return ptr;
|
||||
if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname))
|
||||
return NULL;
|
||||
entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS | __GFP_NOWARN);
|
||||
if (mutex_lock_interruptible(&tomoyo_policy_lock))
|
||||
goto out;
|
||||
ptr = tomoyo_find_namespace(domainname, len);
|
||||
@@ -891,7 +889,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
|
||||
*
|
||||
* @bprm: Pointer to "struct linux_binprm".
|
||||
* @pos: Location to dump.
|
||||
* @dump: Poiner to "struct tomoyo_page_dump".
|
||||
* @dump: Pointer to "struct tomoyo_page_dump".
|
||||
*
|
||||
* Returns true on success, false otherwise.
|
||||
*/
|
||||
|
||||
@@ -463,7 +463,7 @@ static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
|
||||
return;
|
||||
reinject:
|
||||
/*
|
||||
* We can safely reinject this element here bacause
|
||||
* We can safely reinject this element here because
|
||||
* (1) Appending list elements and removing list elements are protected
|
||||
* by tomoyo_policy_lock mutex.
|
||||
* (2) Only this function removes list elements and this function is
|
||||
|
||||
@@ -73,7 +73,7 @@ bool tomoyo_memory_ok(void *ptr)
|
||||
*/
|
||||
void *tomoyo_commit_ok(void *data, const unsigned int size)
|
||||
{
|
||||
void *ptr = kzalloc(size, GFP_NOFS);
|
||||
void *ptr = kzalloc(size, GFP_NOFS | __GFP_NOWARN);
|
||||
|
||||
if (tomoyo_memory_ok(ptr)) {
|
||||
memmove(ptr, data, size);
|
||||
@@ -170,7 +170,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
|
||||
atomic_inc(&ptr->head.users);
|
||||
goto out;
|
||||
}
|
||||
ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
|
||||
ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS | __GFP_NOWARN);
|
||||
if (tomoyo_memory_ok(ptr)) {
|
||||
ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
|
||||
memmove((char *) ptr->entry.name, name, len);
|
||||
|
||||
@@ -131,8 +131,8 @@ static const struct file_operations tomoyo_self_operations = {
|
||||
*/
|
||||
static int tomoyo_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
const int key = ((u8 *) file_inode(file)->i_private)
|
||||
- ((u8 *) NULL);
|
||||
const u8 key = (uintptr_t) file_inode(file)->i_private;
|
||||
|
||||
return tomoyo_open_control(key, file);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ static const struct file_operations tomoyo_operations = {
|
||||
static void __init tomoyo_create_entry(const char *name, const umode_t mode,
|
||||
struct dentry *parent, const u8 key)
|
||||
{
|
||||
securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
|
||||
securityfs_create_file(name, mode, parent, (void *) (uintptr_t) key,
|
||||
&tomoyo_operations);
|
||||
}
|
||||
|
||||
|
||||
@@ -434,59 +434,64 @@ void tomoyo_normalize_line(unsigned char *buffer)
|
||||
*/
|
||||
static bool tomoyo_correct_word2(const char *string, size_t len)
|
||||
{
|
||||
u8 recursion = 20;
|
||||
const char *const start = string;
|
||||
bool in_repetition = false;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
unsigned char e;
|
||||
|
||||
if (!len)
|
||||
goto out;
|
||||
while (len--) {
|
||||
c = *string++;
|
||||
unsigned char c = *string++;
|
||||
|
||||
if (c == '\\') {
|
||||
if (!len--)
|
||||
goto out;
|
||||
c = *string++;
|
||||
if (c >= '0' && c <= '3') {
|
||||
unsigned char d;
|
||||
unsigned char e;
|
||||
|
||||
if (!len-- || !len--)
|
||||
goto out;
|
||||
d = *string++;
|
||||
e = *string++;
|
||||
if (d < '0' || d > '7' || e < '0' || e > '7')
|
||||
goto out;
|
||||
c = tomoyo_make_byte(c, d, e);
|
||||
if (c <= ' ' || c >= 127)
|
||||
continue;
|
||||
goto out;
|
||||
}
|
||||
switch (c) {
|
||||
case '\\': /* "\\" */
|
||||
continue;
|
||||
case '$': /* "\$" */
|
||||
case '+': /* "\+" */
|
||||
case '?': /* "\?" */
|
||||
case 'x': /* "\x" */
|
||||
case 'a': /* "\a" */
|
||||
case '-': /* "\-" */
|
||||
continue;
|
||||
}
|
||||
if (!recursion--)
|
||||
goto out;
|
||||
switch (c) {
|
||||
case '*': /* "\*" */
|
||||
case '@': /* "\@" */
|
||||
case 'x': /* "\x" */
|
||||
case '$': /* "\$" */
|
||||
case 'X': /* "\X" */
|
||||
case 'a': /* "\a" */
|
||||
case 'A': /* "\A" */
|
||||
case '-': /* "\-" */
|
||||
continue;
|
||||
case '{': /* "/\{" */
|
||||
if (string - 3 < start || *(string - 3) != '/')
|
||||
break;
|
||||
goto out;
|
||||
in_repetition = true;
|
||||
continue;
|
||||
case '}': /* "\}/" */
|
||||
if (*string != '/')
|
||||
break;
|
||||
goto out;
|
||||
if (!in_repetition)
|
||||
break;
|
||||
goto out;
|
||||
in_repetition = false;
|
||||
continue;
|
||||
case '0': /* "\ooo" */
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
if (!len-- || !len--)
|
||||
break;
|
||||
d = *string++;
|
||||
e = *string++;
|
||||
if (d < '0' || d > '7' || e < '0' || e > '7')
|
||||
break;
|
||||
c = tomoyo_make_byte(c, d, e);
|
||||
if (c <= ' ' || c >= 127)
|
||||
continue;
|
||||
}
|
||||
goto out;
|
||||
} else if (in_repetition && c == '/') {
|
||||
|
||||
Reference in New Issue
Block a user