diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
| -rw-r--r-- | security/integrity/ima/ima_main.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f4e7266f5ae..6f611874d10 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -29,20 +29,8 @@ int ima_initialized; | |||
| 29 | char *ima_hash = "sha1"; | 29 | char *ima_hash = "sha1"; |
| 30 | static int __init hash_setup(char *str) | 30 | static int __init hash_setup(char *str) |
| 31 | { | 31 | { |
| 32 | const char *op = "hash_setup"; | 32 | if (strncmp(str, "md5", 3) == 0) |
| 33 | const char *hash = "sha1"; | 33 | ima_hash = "md5"; |
| 34 | int result = 0; | ||
| 35 | int audit_info = 0; | ||
| 36 | |||
| 37 | if (strncmp(str, "md5", 3) == 0) { | ||
| 38 | hash = "md5"; | ||
| 39 | ima_hash = str; | ||
| 40 | } else if (strncmp(str, "sha1", 4) != 0) { | ||
| 41 | hash = "invalid_hash_type"; | ||
| 42 | result = 1; | ||
| 43 | } | ||
| 44 | integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash, | ||
| 45 | result, audit_info); | ||
| 46 | return 1; | 34 | return 1; |
| 47 | } | 35 | } |
| 48 | __setup("ima_hash=", hash_setup); | 36 | __setup("ima_hash=", hash_setup); |
| @@ -128,10 +116,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
| 128 | { | 116 | { |
| 129 | int rc = 0; | 117 | int rc = 0; |
| 130 | 118 | ||
| 131 | if (IS_ERR(file)) { | ||
| 132 | pr_info("%s dentry_open failed\n", filename); | ||
| 133 | return rc; | ||
| 134 | } | ||
| 135 | iint->opencount++; | 119 | iint->opencount++; |
| 136 | iint->readcount++; | 120 | iint->readcount++; |
| 137 | 121 | ||
| @@ -141,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
| 141 | return rc; | 125 | return rc; |
| 142 | } | 126 | } |
| 143 | 127 | ||
| 128 | static void ima_update_counts(struct ima_iint_cache *iint, int mask) | ||
| 129 | { | ||
| 130 | iint->opencount++; | ||
| 131 | if ((mask & MAY_WRITE) || (mask == 0)) | ||
| 132 | iint->writecount++; | ||
| 133 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
| 134 | iint->readcount++; | ||
| 135 | } | ||
| 136 | |||
| 144 | /** | 137 | /** |
| 145 | * ima_path_check - based on policy, collect/store measurement. | 138 | * ima_path_check - based on policy, collect/store measurement. |
| 146 | * @path: contains a pointer to the path to be measured | 139 | * @path: contains a pointer to the path to be measured |
| @@ -156,10 +149,10 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
| 156 | * - Opening a file for read when already open for write, | 149 | * - Opening a file for read when already open for write, |
| 157 | * could result in a file measurement error. | 150 | * could result in a file measurement error. |
| 158 | * | 151 | * |
| 159 | * Return 0 on success, an error code on failure. | 152 | * Always return 0 and audit dentry_open failures. |
| 160 | * (Based on the results of appraise_measurement().) | 153 | * (Return code will be based upon measurement appraisal.) |
| 161 | */ | 154 | */ |
| 162 | int ima_path_check(struct path *path, int mask) | 155 | int ima_path_check(struct path *path, int mask, int update_counts) |
| 163 | { | 156 | { |
| 164 | struct inode *inode = path->dentry->d_inode; | 157 | struct inode *inode = path->dentry->d_inode; |
| 165 | struct ima_iint_cache *iint; | 158 | struct ima_iint_cache *iint; |
| @@ -173,11 +166,8 @@ int ima_path_check(struct path *path, int mask) | |||
| 173 | return 0; | 166 | return 0; |
| 174 | 167 | ||
| 175 | mutex_lock(&iint->mutex); | 168 | mutex_lock(&iint->mutex); |
| 176 | iint->opencount++; | 169 | if (update_counts) |
| 177 | if ((mask & MAY_WRITE) || (mask == 0)) | 170 | ima_update_counts(iint, mask); |
| 178 | iint->writecount++; | ||
| 179 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
| 180 | iint->readcount++; | ||
| 181 | 171 | ||
| 182 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); | 172 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); |
| 183 | if (rc < 0) | 173 | if (rc < 0) |
| @@ -196,7 +186,19 @@ int ima_path_check(struct path *path, int mask) | |||
| 196 | struct dentry *dentry = dget(path->dentry); | 186 | struct dentry *dentry = dget(path->dentry); |
| 197 | struct vfsmount *mnt = mntget(path->mnt); | 187 | struct vfsmount *mnt = mntget(path->mnt); |
| 198 | 188 | ||
| 199 | file = dentry_open(dentry, mnt, O_RDONLY, current->cred); | 189 | file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, |
| 190 | current_cred()); | ||
| 191 | if (IS_ERR(file)) { | ||
| 192 | int audit_info = 0; | ||
| 193 | |||
| 194 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, | ||
| 195 | dentry->d_name.name, | ||
| 196 | "add_measurement", | ||
| 197 | "dentry_open failed", | ||
| 198 | 1, audit_info); | ||
| 199 | file = NULL; | ||
| 200 | goto out; | ||
| 201 | } | ||
| 200 | rc = get_path_measurement(iint, file, dentry->d_name.name); | 202 | rc = get_path_measurement(iint, file, dentry->d_name.name); |
| 201 | } | 203 | } |
| 202 | out: | 204 | out: |
| @@ -206,6 +208,7 @@ out: | |||
| 206 | kref_put(&iint->refcount, iint_free); | 208 | kref_put(&iint->refcount, iint_free); |
| 207 | return 0; | 209 | return 0; |
| 208 | } | 210 | } |
| 211 | EXPORT_SYMBOL_GPL(ima_path_check); | ||
| 209 | 212 | ||
| 210 | static int process_measurement(struct file *file, const unsigned char *filename, | 213 | static int process_measurement(struct file *file, const unsigned char *filename, |
| 211 | int mask, int function) | 214 | int mask, int function) |
| @@ -234,7 +237,16 @@ out: | |||
| 234 | return rc; | 237 | return rc; |
| 235 | } | 238 | } |
| 236 | 239 | ||
| 237 | static void opencount_get(struct file *file) | 240 | /* |
| 241 | * ima_opens_get - increment file counts | ||
| 242 | * | ||
| 243 | * - for IPC shm and shmat file. | ||
| 244 | * - for nfsd exported files. | ||
| 245 | * | ||
| 246 | * Increment the counts for these files to prevent unnecessary | ||
| 247 | * imbalance messages. | ||
| 248 | */ | ||
| 249 | void ima_counts_get(struct file *file) | ||
| 238 | { | 250 | { |
| 239 | struct inode *inode = file->f_dentry->d_inode; | 251 | struct inode *inode = file->f_dentry->d_inode; |
| 240 | struct ima_iint_cache *iint; | 252 | struct ima_iint_cache *iint; |
| @@ -246,8 +258,14 @@ static void opencount_get(struct file *file) | |||
| 246 | return; | 258 | return; |
| 247 | mutex_lock(&iint->mutex); | 259 | mutex_lock(&iint->mutex); |
| 248 | iint->opencount++; | 260 | iint->opencount++; |
| 261 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
| 262 | iint->readcount++; | ||
| 263 | |||
| 264 | if (file->f_mode & FMODE_WRITE) | ||
| 265 | iint->writecount++; | ||
| 249 | mutex_unlock(&iint->mutex); | 266 | mutex_unlock(&iint->mutex); |
| 250 | } | 267 | } |
| 268 | EXPORT_SYMBOL_GPL(ima_counts_get); | ||
| 251 | 269 | ||
| 252 | /** | 270 | /** |
| 253 | * ima_file_mmap - based on policy, collect/store measurement. | 271 | * ima_file_mmap - based on policy, collect/store measurement. |
| @@ -272,18 +290,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
| 272 | return 0; | 290 | return 0; |
| 273 | } | 291 | } |
| 274 | 292 | ||
| 275 | /* | ||
| 276 | * ima_shm_check - IPC shm and shmat create/fput a file | ||
| 277 | * | ||
| 278 | * Maintain the opencount for these files to prevent unnecessary | ||
| 279 | * imbalance messages. | ||
| 280 | */ | ||
| 281 | void ima_shm_check(struct file *file) | ||
| 282 | { | ||
| 283 | opencount_get(file); | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | |||
| 287 | /** | 293 | /** |
| 288 | * ima_bprm_check - based on policy, collect/store measurement. | 294 | * ima_bprm_check - based on policy, collect/store measurement. |
| 289 | * @bprm: contains the linux_binprm structure | 295 | * @bprm: contains the linux_binprm structure |
