Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* AFS security handling
0003  *
0004  * Copyright (C) 2007, 2017 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/init.h>
0009 #include <linux/slab.h>
0010 #include <linux/fs.h>
0011 #include <linux/ctype.h>
0012 #include <linux/sched.h>
0013 #include <linux/hashtable.h>
0014 #include <keys/rxrpc-type.h>
0015 #include "internal.h"
0016 
0017 static DEFINE_HASHTABLE(afs_permits_cache, 10);
0018 static DEFINE_SPINLOCK(afs_permits_lock);
0019 
0020 /*
0021  * get a key
0022  */
0023 struct key *afs_request_key(struct afs_cell *cell)
0024 {
0025     struct key *key;
0026 
0027     _enter("{%x}", key_serial(cell->anonymous_key));
0028 
0029     _debug("key %s", cell->anonymous_key->description);
0030     key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description,
0031                   cell->net->net, NULL);
0032     if (IS_ERR(key)) {
0033         if (PTR_ERR(key) != -ENOKEY) {
0034             _leave(" = %ld", PTR_ERR(key));
0035             return key;
0036         }
0037 
0038         /* act as anonymous user */
0039         _leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
0040         return key_get(cell->anonymous_key);
0041     } else {
0042         /* act as authorised user */
0043         _leave(" = {%x} [auth]", key_serial(key));
0044         return key;
0045     }
0046 }
0047 
0048 /*
0049  * Get a key when pathwalk is in rcuwalk mode.
0050  */
0051 struct key *afs_request_key_rcu(struct afs_cell *cell)
0052 {
0053     struct key *key;
0054 
0055     _enter("{%x}", key_serial(cell->anonymous_key));
0056 
0057     _debug("key %s", cell->anonymous_key->description);
0058     key = request_key_net_rcu(&key_type_rxrpc,
0059                   cell->anonymous_key->description,
0060                   cell->net->net);
0061     if (IS_ERR(key)) {
0062         if (PTR_ERR(key) != -ENOKEY) {
0063             _leave(" = %ld", PTR_ERR(key));
0064             return key;
0065         }
0066 
0067         /* act as anonymous user */
0068         _leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
0069         return key_get(cell->anonymous_key);
0070     } else {
0071         /* act as authorised user */
0072         _leave(" = {%x} [auth]", key_serial(key));
0073         return key;
0074     }
0075 }
0076 
0077 /*
0078  * Dispose of a list of permits.
0079  */
0080 static void afs_permits_rcu(struct rcu_head *rcu)
0081 {
0082     struct afs_permits *permits =
0083         container_of(rcu, struct afs_permits, rcu);
0084     int i;
0085 
0086     for (i = 0; i < permits->nr_permits; i++)
0087         key_put(permits->permits[i].key);
0088     kfree(permits);
0089 }
0090 
0091 /*
0092  * Discard a permission cache.
0093  */
0094 void afs_put_permits(struct afs_permits *permits)
0095 {
0096     if (permits && refcount_dec_and_test(&permits->usage)) {
0097         spin_lock(&afs_permits_lock);
0098         hash_del_rcu(&permits->hash_node);
0099         spin_unlock(&afs_permits_lock);
0100         call_rcu(&permits->rcu, afs_permits_rcu);
0101     }
0102 }
0103 
0104 /*
0105  * Clear a permit cache on callback break.
0106  */
0107 void afs_clear_permits(struct afs_vnode *vnode)
0108 {
0109     struct afs_permits *permits;
0110 
0111     spin_lock(&vnode->lock);
0112     permits = rcu_dereference_protected(vnode->permit_cache,
0113                         lockdep_is_held(&vnode->lock));
0114     RCU_INIT_POINTER(vnode->permit_cache, NULL);
0115     spin_unlock(&vnode->lock);
0116 
0117     afs_put_permits(permits);
0118 }
0119 
0120 /*
0121  * Hash a list of permits.  Use simple addition to make it easy to add an extra
0122  * one at an as-yet indeterminate position in the list.
0123  */
0124 static void afs_hash_permits(struct afs_permits *permits)
0125 {
0126     unsigned long h = permits->nr_permits;
0127     int i;
0128 
0129     for (i = 0; i < permits->nr_permits; i++) {
0130         h += (unsigned long)permits->permits[i].key / sizeof(void *);
0131         h += permits->permits[i].access;
0132     }
0133 
0134     permits->h = h;
0135 }
0136 
0137 /*
0138  * Cache the CallerAccess result obtained from doing a fileserver operation
0139  * that returned a vnode status for a particular key.  If a callback break
0140  * occurs whilst the operation was in progress then we have to ditch the cache
0141  * as the ACL *may* have changed.
0142  */
0143 void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
0144               unsigned int cb_break, struct afs_status_cb *scb)
0145 {
0146     struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL;
0147     afs_access_t caller_access = scb->status.caller_access;
0148     size_t size = 0;
0149     bool changed = false;
0150     int i, j;
0151 
0152     _enter("{%llx:%llu},%x,%x",
0153            vnode->fid.vid, vnode->fid.vnode, key_serial(key), caller_access);
0154 
0155     rcu_read_lock();
0156 
0157     /* Check for the common case first: We got back the same access as last
0158      * time we tried and already have it recorded.
0159      */
0160     permits = rcu_dereference(vnode->permit_cache);
0161     if (permits) {
0162         if (!permits->invalidated) {
0163             for (i = 0; i < permits->nr_permits; i++) {
0164                 if (permits->permits[i].key < key)
0165                     continue;
0166                 if (permits->permits[i].key > key)
0167                     break;
0168                 if (permits->permits[i].access != caller_access) {
0169                     changed = true;
0170                     break;
0171                 }
0172 
0173                 if (afs_cb_is_broken(cb_break, vnode)) {
0174                     changed = true;
0175                     break;
0176                 }
0177 
0178                 /* The cache is still good. */
0179                 rcu_read_unlock();
0180                 return;
0181             }
0182         }
0183 
0184         changed |= permits->invalidated;
0185         size = permits->nr_permits;
0186 
0187         /* If this set of permits is now wrong, clear the permits
0188          * pointer so that no one tries to use the stale information.
0189          */
0190         if (changed) {
0191             spin_lock(&vnode->lock);
0192             if (permits != rcu_access_pointer(vnode->permit_cache))
0193                 goto someone_else_changed_it_unlock;
0194             RCU_INIT_POINTER(vnode->permit_cache, NULL);
0195             spin_unlock(&vnode->lock);
0196 
0197             afs_put_permits(permits);
0198             permits = NULL;
0199             size = 0;
0200         }
0201     }
0202 
0203     if (afs_cb_is_broken(cb_break, vnode))
0204         goto someone_else_changed_it;
0205 
0206     /* We need a ref on any permits list we want to copy as we'll have to
0207      * drop the lock to do memory allocation.
0208      */
0209     if (permits && !refcount_inc_not_zero(&permits->usage))
0210         goto someone_else_changed_it;
0211 
0212     rcu_read_unlock();
0213 
0214     /* Speculatively create a new list with the revised permission set.  We
0215      * discard this if we find an extant match already in the hash, but
0216      * it's easier to compare with memcmp this way.
0217      *
0218      * We fill in the key pointers at this time, but we don't get the refs
0219      * yet.
0220      */
0221     size++;
0222     new = kzalloc(struct_size(new, permits, size), GFP_NOFS);
0223     if (!new)
0224         goto out_put;
0225 
0226     refcount_set(&new->usage, 1);
0227     new->nr_permits = size;
0228     i = j = 0;
0229     if (permits) {
0230         for (i = 0; i < permits->nr_permits; i++) {
0231             if (j == i && permits->permits[i].key > key) {
0232                 new->permits[j].key = key;
0233                 new->permits[j].access = caller_access;
0234                 j++;
0235             }
0236             new->permits[j].key = permits->permits[i].key;
0237             new->permits[j].access = permits->permits[i].access;
0238             j++;
0239         }
0240     }
0241 
0242     if (j == i) {
0243         new->permits[j].key = key;
0244         new->permits[j].access = caller_access;
0245     }
0246 
0247     afs_hash_permits(new);
0248 
0249     /* Now see if the permit list we want is actually already available */
0250     spin_lock(&afs_permits_lock);
0251 
0252     hash_for_each_possible(afs_permits_cache, xpermits, hash_node, new->h) {
0253         if (xpermits->h != new->h ||
0254             xpermits->invalidated ||
0255             xpermits->nr_permits != new->nr_permits ||
0256             memcmp(xpermits->permits, new->permits,
0257                new->nr_permits * sizeof(struct afs_permit)) != 0)
0258             continue;
0259 
0260         if (refcount_inc_not_zero(&xpermits->usage)) {
0261             replacement = xpermits;
0262             goto found;
0263         }
0264 
0265         break;
0266     }
0267 
0268     for (i = 0; i < new->nr_permits; i++)
0269         key_get(new->permits[i].key);
0270     hash_add_rcu(afs_permits_cache, &new->hash_node, new->h);
0271     replacement = new;
0272     new = NULL;
0273 
0274 found:
0275     spin_unlock(&afs_permits_lock);
0276 
0277     kfree(new);
0278 
0279     rcu_read_lock();
0280     spin_lock(&vnode->lock);
0281     zap = rcu_access_pointer(vnode->permit_cache);
0282     if (!afs_cb_is_broken(cb_break, vnode) && zap == permits)
0283         rcu_assign_pointer(vnode->permit_cache, replacement);
0284     else
0285         zap = replacement;
0286     spin_unlock(&vnode->lock);
0287     rcu_read_unlock();
0288     afs_put_permits(zap);
0289 out_put:
0290     afs_put_permits(permits);
0291     return;
0292 
0293 someone_else_changed_it_unlock:
0294     spin_unlock(&vnode->lock);
0295 someone_else_changed_it:
0296     /* Someone else changed the cache under us - don't recheck at this
0297      * time.
0298      */
0299     rcu_read_unlock();
0300     return;
0301 }
0302 
0303 static bool afs_check_permit_rcu(struct afs_vnode *vnode, struct key *key,
0304                  afs_access_t *_access)
0305 {
0306     const struct afs_permits *permits;
0307     int i;
0308 
0309     _enter("{%llx:%llu},%x",
0310            vnode->fid.vid, vnode->fid.vnode, key_serial(key));
0311 
0312     /* check the permits to see if we've got one yet */
0313     if (key == vnode->volume->cell->anonymous_key) {
0314         *_access = vnode->status.anon_access;
0315         _leave(" = t [anon %x]", *_access);
0316         return true;
0317     }
0318 
0319     permits = rcu_dereference(vnode->permit_cache);
0320     if (permits) {
0321         for (i = 0; i < permits->nr_permits; i++) {
0322             if (permits->permits[i].key < key)
0323                 continue;
0324             if (permits->permits[i].key > key)
0325                 break;
0326 
0327             *_access = permits->permits[i].access;
0328             _leave(" = %u [perm %x]", !permits->invalidated, *_access);
0329             return !permits->invalidated;
0330         }
0331     }
0332 
0333     _leave(" = f");
0334     return false;
0335 }
0336 
0337 /*
0338  * check with the fileserver to see if the directory or parent directory is
0339  * permitted to be accessed with this authorisation, and if so, what access it
0340  * is granted
0341  */
0342 int afs_check_permit(struct afs_vnode *vnode, struct key *key,
0343              afs_access_t *_access)
0344 {
0345     struct afs_permits *permits;
0346     bool valid = false;
0347     int i, ret;
0348 
0349     _enter("{%llx:%llu},%x",
0350            vnode->fid.vid, vnode->fid.vnode, key_serial(key));
0351 
0352     /* check the permits to see if we've got one yet */
0353     if (key == vnode->volume->cell->anonymous_key) {
0354         _debug("anon");
0355         *_access = vnode->status.anon_access;
0356         valid = true;
0357     } else {
0358         rcu_read_lock();
0359         permits = rcu_dereference(vnode->permit_cache);
0360         if (permits) {
0361             for (i = 0; i < permits->nr_permits; i++) {
0362                 if (permits->permits[i].key < key)
0363                     continue;
0364                 if (permits->permits[i].key > key)
0365                     break;
0366 
0367                 *_access = permits->permits[i].access;
0368                 valid = !permits->invalidated;
0369                 break;
0370             }
0371         }
0372         rcu_read_unlock();
0373     }
0374 
0375     if (!valid) {
0376         /* Check the status on the file we're actually interested in
0377          * (the post-processing will cache the result).
0378          */
0379         _debug("no valid permit");
0380 
0381         ret = afs_fetch_status(vnode, key, false, _access);
0382         if (ret < 0) {
0383             *_access = 0;
0384             _leave(" = %d", ret);
0385             return ret;
0386         }
0387     }
0388 
0389     _leave(" = 0 [access %x]", *_access);
0390     return 0;
0391 }
0392 
0393 /*
0394  * check the permissions on an AFS file
0395  * - AFS ACLs are attached to directories only, and a file is controlled by its
0396  *   parent directory's ACL
0397  */
0398 int afs_permission(struct user_namespace *mnt_userns, struct inode *inode,
0399            int mask)
0400 {
0401     struct afs_vnode *vnode = AFS_FS_I(inode);
0402     afs_access_t access;
0403     struct key *key;
0404     int ret = 0;
0405 
0406     _enter("{{%llx:%llu},%lx},%x,",
0407            vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);
0408 
0409     if (mask & MAY_NOT_BLOCK) {
0410         key = afs_request_key_rcu(vnode->volume->cell);
0411         if (IS_ERR(key))
0412             return -ECHILD;
0413 
0414         ret = -ECHILD;
0415         if (!afs_check_validity(vnode) ||
0416             !afs_check_permit_rcu(vnode, key, &access))
0417             goto error;
0418     } else {
0419         key = afs_request_key(vnode->volume->cell);
0420         if (IS_ERR(key)) {
0421             _leave(" = %ld [key]", PTR_ERR(key));
0422             return PTR_ERR(key);
0423         }
0424 
0425         ret = afs_validate(vnode, key);
0426         if (ret < 0)
0427             goto error;
0428 
0429         /* check the permits to see if we've got one yet */
0430         ret = afs_check_permit(vnode, key, &access);
0431         if (ret < 0)
0432             goto error;
0433     }
0434 
0435     /* interpret the access mask */
0436     _debug("REQ %x ACC %x on %s",
0437            mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file");
0438 
0439     ret = 0;
0440     if (S_ISDIR(inode->i_mode)) {
0441         if (mask & (MAY_EXEC | MAY_READ | MAY_CHDIR)) {
0442             if (!(access & AFS_ACE_LOOKUP))
0443                 goto permission_denied;
0444         }
0445         if (mask & MAY_WRITE) {
0446             if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */
0447                     AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */
0448                 goto permission_denied;
0449         }
0450     } else {
0451         if (!(access & AFS_ACE_LOOKUP))
0452             goto permission_denied;
0453         if ((mask & MAY_EXEC) && !(inode->i_mode & S_IXUSR))
0454             goto permission_denied;
0455         if (mask & (MAY_EXEC | MAY_READ)) {
0456             if (!(access & AFS_ACE_READ))
0457                 goto permission_denied;
0458             if (!(inode->i_mode & S_IRUSR))
0459                 goto permission_denied;
0460         } else if (mask & MAY_WRITE) {
0461             if (!(access & AFS_ACE_WRITE))
0462                 goto permission_denied;
0463             if (!(inode->i_mode & S_IWUSR))
0464                 goto permission_denied;
0465         }
0466     }
0467 
0468     key_put(key);
0469     _leave(" = %d", ret);
0470     return ret;
0471 
0472 permission_denied:
0473     ret = -EACCES;
0474 error:
0475     key_put(key);
0476     _leave(" = %d", ret);
0477     return ret;
0478 }
0479 
0480 void __exit afs_clean_up_permit_cache(void)
0481 {
0482     int i;
0483 
0484     for (i = 0; i < HASH_SIZE(afs_permits_cache); i++)
0485         WARN_ON_ONCE(!hlist_empty(&afs_permits_cache[i]));
0486 
0487 }