| David Howells | 9ae326a | 2009-04-03 16:42:41 +0100 | [diff] [blame] | 1 | /* CacheFiles security management | 
|  | 2 | * | 
|  | 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 
|  | 4 | * Written by David Howells (dhowells@redhat.com) | 
|  | 5 | * | 
|  | 6 | * This program is free software; you can redistribute it and/or | 
|  | 7 | * modify it under the terms of the GNU General Public Licence | 
|  | 8 | * as published by the Free Software Foundation; either version | 
|  | 9 | * 2 of the Licence, or (at your option) any later version. | 
|  | 10 | */ | 
|  | 11 |  | 
|  | 12 | #include <linux/fs.h> | 
|  | 13 | #include <linux/cred.h> | 
|  | 14 | #include "internal.h" | 
|  | 15 |  | 
|  | 16 | /* | 
|  | 17 | * determine the security context within which we access the cache from within | 
|  | 18 | * the kernel | 
|  | 19 | */ | 
|  | 20 | int cachefiles_get_security_ID(struct cachefiles_cache *cache) | 
|  | 21 | { | 
|  | 22 | struct cred *new; | 
|  | 23 | int ret; | 
|  | 24 |  | 
|  | 25 | _enter("{%s}", cache->secctx); | 
|  | 26 |  | 
|  | 27 | new = prepare_kernel_cred(current); | 
|  | 28 | if (!new) { | 
|  | 29 | ret = -ENOMEM; | 
|  | 30 | goto error; | 
|  | 31 | } | 
|  | 32 |  | 
|  | 33 | if (cache->secctx) { | 
|  | 34 | ret = set_security_override_from_ctx(new, cache->secctx); | 
|  | 35 | if (ret < 0) { | 
|  | 36 | put_cred(new); | 
|  | 37 | printk(KERN_ERR "CacheFiles:" | 
|  | 38 | " Security denies permission to nominate" | 
|  | 39 | " security context: error %d\n", | 
|  | 40 | ret); | 
|  | 41 | goto error; | 
|  | 42 | } | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | cache->cache_cred = new; | 
|  | 46 | ret = 0; | 
|  | 47 | error: | 
|  | 48 | _leave(" = %d", ret); | 
|  | 49 | return ret; | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | /* | 
|  | 53 | * see if mkdir and create can be performed in the root directory | 
|  | 54 | */ | 
|  | 55 | static int cachefiles_check_cache_dir(struct cachefiles_cache *cache, | 
|  | 56 | struct dentry *root) | 
|  | 57 | { | 
|  | 58 | int ret; | 
|  | 59 |  | 
|  | 60 | ret = security_inode_mkdir(root->d_inode, root, 0); | 
|  | 61 | if (ret < 0) { | 
|  | 62 | printk(KERN_ERR "CacheFiles:" | 
|  | 63 | " Security denies permission to make dirs: error %d", | 
|  | 64 | ret); | 
|  | 65 | return ret; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | ret = security_inode_create(root->d_inode, root, 0); | 
|  | 69 | if (ret < 0) | 
|  | 70 | printk(KERN_ERR "CacheFiles:" | 
|  | 71 | " Security denies permission to create files: error %d", | 
|  | 72 | ret); | 
|  | 73 |  | 
|  | 74 | return ret; | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | /* | 
|  | 78 | * check the security details of the on-disk cache | 
|  | 79 | * - must be called with security override in force | 
| David Howells | 7ac512a | 2010-05-12 15:34:03 +0100 | [diff] [blame] | 80 | * - must return with a security override in force - even in the case of an | 
|  | 81 | *   error | 
| David Howells | 9ae326a | 2009-04-03 16:42:41 +0100 | [diff] [blame] | 82 | */ | 
|  | 83 | int cachefiles_determine_cache_security(struct cachefiles_cache *cache, | 
|  | 84 | struct dentry *root, | 
|  | 85 | const struct cred **_saved_cred) | 
|  | 86 | { | 
|  | 87 | struct cred *new; | 
|  | 88 | int ret; | 
|  | 89 |  | 
|  | 90 | _enter(""); | 
|  | 91 |  | 
|  | 92 | /* duplicate the cache creds for COW (the override is currently in | 
|  | 93 | * force, so we can use prepare_creds() to do this) */ | 
|  | 94 | new = prepare_creds(); | 
|  | 95 | if (!new) | 
|  | 96 | return -ENOMEM; | 
|  | 97 |  | 
|  | 98 | cachefiles_end_secure(cache, *_saved_cred); | 
|  | 99 |  | 
|  | 100 | /* use the cache root dir's security context as the basis with | 
|  | 101 | * which create files */ | 
|  | 102 | ret = set_create_files_as(new, root->d_inode); | 
|  | 103 | if (ret < 0) { | 
| David Howells | 7ac512a | 2010-05-12 15:34:03 +0100 | [diff] [blame] | 104 | abort_creds(new); | 
|  | 105 | cachefiles_begin_secure(cache, _saved_cred); | 
| David Howells | 9ae326a | 2009-04-03 16:42:41 +0100 | [diff] [blame] | 106 | _leave(" = %d [cfa]", ret); | 
|  | 107 | return ret; | 
|  | 108 | } | 
|  | 109 |  | 
|  | 110 | put_cred(cache->cache_cred); | 
|  | 111 | cache->cache_cred = new; | 
|  | 112 |  | 
|  | 113 | cachefiles_begin_secure(cache, _saved_cred); | 
|  | 114 | ret = cachefiles_check_cache_dir(cache, root); | 
|  | 115 |  | 
|  | 116 | if (ret == -EOPNOTSUPP) | 
|  | 117 | ret = 0; | 
|  | 118 | _leave(" = %d", ret); | 
|  | 119 | return ret; | 
|  | 120 | } |