18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * security/tomoyo/tomoyo.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/lsm_hooks.h> 98c2ecf20Sopenharmony_ci#include "common.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/** 128c2ecf20Sopenharmony_ci * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Returns pointer to "struct tomoyo_domain_info" for current thread. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_cistruct tomoyo_domain_info *tomoyo_domain(void) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(current); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci if (s->old_domain_info && !current->in_execve) { 218c2ecf20Sopenharmony_ci atomic_dec(&s->old_domain_info->users); 228c2ecf20Sopenharmony_ci s->old_domain_info = NULL; 238c2ecf20Sopenharmony_ci } 248c2ecf20Sopenharmony_ci return s->domain_info; 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/** 288c2ecf20Sopenharmony_ci * tomoyo_cred_prepare - Target for security_prepare_creds(). 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * @new: Pointer to "struct cred". 318c2ecf20Sopenharmony_ci * @old: Pointer to "struct cred". 328c2ecf20Sopenharmony_ci * @gfp: Memory allocation flags. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Returns 0. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistatic int tomoyo_cred_prepare(struct cred *new, const struct cred *old, 378c2ecf20Sopenharmony_ci gfp_t gfp) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci /* Restore old_domain_info saved by previous execve() request. */ 408c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(current); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (s->old_domain_info && !current->in_execve) { 438c2ecf20Sopenharmony_ci atomic_dec(&s->domain_info->users); 448c2ecf20Sopenharmony_ci s->domain_info = s->old_domain_info; 458c2ecf20Sopenharmony_ci s->old_domain_info = NULL; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci return 0; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/** 518c2ecf20Sopenharmony_ci * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * @bprm: Pointer to "struct linux_binprm". 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_cistatic void tomoyo_bprm_committed_creds(struct linux_binprm *bprm) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci /* Clear old_domain_info saved by execve() request. */ 588c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(current); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci atomic_dec(&s->old_domain_info->users); 618c2ecf20Sopenharmony_ci s->old_domain_info = NULL; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER 658c2ecf20Sopenharmony_ci/** 668c2ecf20Sopenharmony_ci * tomoyo_bprm_for_exec - Target for security_bprm_creds_for_exec(). 678c2ecf20Sopenharmony_ci * 688c2ecf20Sopenharmony_ci * @bprm: Pointer to "struct linux_binprm". 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * Returns 0. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_cistatic int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested 768c2ecf20Sopenharmony_ci * for the first time. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci if (!tomoyo_policy_loaded) 798c2ecf20Sopenharmony_ci tomoyo_load_policy(bprm->filename); 808c2ecf20Sopenharmony_ci return 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci#endif 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/** 858c2ecf20Sopenharmony_ci * tomoyo_bprm_check_security - Target for security_bprm_check(). 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * @bprm: Pointer to "struct linux_binprm". 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistatic int tomoyo_bprm_check_security(struct linux_binprm *bprm) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(current); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* 968c2ecf20Sopenharmony_ci * Execute permission is checked against pathname passed to execve() 978c2ecf20Sopenharmony_ci * using current domain. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci if (!s->old_domain_info) { 1008c2ecf20Sopenharmony_ci const int idx = tomoyo_read_lock(); 1018c2ecf20Sopenharmony_ci const int err = tomoyo_find_next_domain(bprm); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci tomoyo_read_unlock(idx); 1048c2ecf20Sopenharmony_ci return err; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci /* 1078c2ecf20Sopenharmony_ci * Read permission is checked against interpreters using next domain. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci return tomoyo_check_open_permission(s->domain_info, 1108c2ecf20Sopenharmony_ci &bprm->file->f_path, O_RDONLY); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/** 1148c2ecf20Sopenharmony_ci * tomoyo_inode_getattr - Target for security_inode_getattr(). 1158c2ecf20Sopenharmony_ci * 1168c2ecf20Sopenharmony_ci * @mnt: Pointer to "struct vfsmount". 1178c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 1188c2ecf20Sopenharmony_ci * 1198c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistatic int tomoyo_inode_getattr(const struct path *path) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/** 1278c2ecf20Sopenharmony_ci * tomoyo_path_truncate - Target for security_path_truncate(). 1288c2ecf20Sopenharmony_ci * 1298c2ecf20Sopenharmony_ci * @path: Pointer to "struct path". 1308c2ecf20Sopenharmony_ci * 1318c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cistatic int tomoyo_path_truncate(const struct path *path) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/** 1398c2ecf20Sopenharmony_ci * tomoyo_path_unlink - Target for security_path_unlink(). 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * @parent: Pointer to "struct path". 1428c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_cistatic int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct path path = { .mnt = parent->mnt, .dentry = dentry }; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/** 1548c2ecf20Sopenharmony_ci * tomoyo_path_mkdir - Target for security_path_mkdir(). 1558c2ecf20Sopenharmony_ci * 1568c2ecf20Sopenharmony_ci * @parent: Pointer to "struct path". 1578c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 1588c2ecf20Sopenharmony_ci * @mode: DAC permission mode. 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1618c2ecf20Sopenharmony_ci */ 1628c2ecf20Sopenharmony_cistatic int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, 1638c2ecf20Sopenharmony_ci umode_t mode) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct path path = { .mnt = parent->mnt, .dentry = dentry }; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, 1688c2ecf20Sopenharmony_ci mode & S_IALLUGO); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/** 1728c2ecf20Sopenharmony_ci * tomoyo_path_rmdir - Target for security_path_rmdir(). 1738c2ecf20Sopenharmony_ci * 1748c2ecf20Sopenharmony_ci * @parent: Pointer to "struct path". 1758c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 1768c2ecf20Sopenharmony_ci * 1778c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_cistatic int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct path path = { .mnt = parent->mnt, .dentry = dentry }; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/** 1878c2ecf20Sopenharmony_ci * tomoyo_path_symlink - Target for security_path_symlink(). 1888c2ecf20Sopenharmony_ci * 1898c2ecf20Sopenharmony_ci * @parent: Pointer to "struct path". 1908c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 1918c2ecf20Sopenharmony_ci * @old_name: Symlink's content. 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_cistatic int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, 1968c2ecf20Sopenharmony_ci const char *old_name) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct path path = { .mnt = parent->mnt, .dentry = dentry }; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci/** 2048c2ecf20Sopenharmony_ci * tomoyo_path_mknod - Target for security_path_mknod(). 2058c2ecf20Sopenharmony_ci * 2068c2ecf20Sopenharmony_ci * @parent: Pointer to "struct path". 2078c2ecf20Sopenharmony_ci * @dentry: Pointer to "struct dentry". 2088c2ecf20Sopenharmony_ci * @mode: DAC permission mode. 2098c2ecf20Sopenharmony_ci * @dev: Device attributes. 2108c2ecf20Sopenharmony_ci * 2118c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_cistatic int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, 2148c2ecf20Sopenharmony_ci umode_t mode, unsigned int dev) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct path path = { .mnt = parent->mnt, .dentry = dentry }; 2178c2ecf20Sopenharmony_ci int type = TOMOYO_TYPE_CREATE; 2188c2ecf20Sopenharmony_ci const unsigned int perm = mode & S_IALLUGO; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci switch (mode & S_IFMT) { 2218c2ecf20Sopenharmony_ci case S_IFCHR: 2228c2ecf20Sopenharmony_ci type = TOMOYO_TYPE_MKCHAR; 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci case S_IFBLK: 2258c2ecf20Sopenharmony_ci type = TOMOYO_TYPE_MKBLOCK; 2268c2ecf20Sopenharmony_ci break; 2278c2ecf20Sopenharmony_ci default: 2288c2ecf20Sopenharmony_ci goto no_dev; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci return tomoyo_mkdev_perm(type, &path, perm, dev); 2318c2ecf20Sopenharmony_ci no_dev: 2328c2ecf20Sopenharmony_ci switch (mode & S_IFMT) { 2338c2ecf20Sopenharmony_ci case S_IFIFO: 2348c2ecf20Sopenharmony_ci type = TOMOYO_TYPE_MKFIFO; 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci case S_IFSOCK: 2378c2ecf20Sopenharmony_ci type = TOMOYO_TYPE_MKSOCK; 2388c2ecf20Sopenharmony_ci break; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci return tomoyo_path_number_perm(type, &path, perm); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci/** 2448c2ecf20Sopenharmony_ci * tomoyo_path_link - Target for security_path_link(). 2458c2ecf20Sopenharmony_ci * 2468c2ecf20Sopenharmony_ci * @old_dentry: Pointer to "struct dentry". 2478c2ecf20Sopenharmony_ci * @new_dir: Pointer to "struct path". 2488c2ecf20Sopenharmony_ci * @new_dentry: Pointer to "struct dentry". 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_cistatic int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, 2538c2ecf20Sopenharmony_ci struct dentry *new_dentry) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; 2568c2ecf20Sopenharmony_ci struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/** 2628c2ecf20Sopenharmony_ci * tomoyo_path_rename - Target for security_path_rename(). 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * @old_parent: Pointer to "struct path". 2658c2ecf20Sopenharmony_ci * @old_dentry: Pointer to "struct dentry". 2668c2ecf20Sopenharmony_ci * @new_parent: Pointer to "struct path". 2678c2ecf20Sopenharmony_ci * @new_dentry: Pointer to "struct dentry". 2688c2ecf20Sopenharmony_ci * 2698c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_cistatic int tomoyo_path_rename(const struct path *old_parent, 2728c2ecf20Sopenharmony_ci struct dentry *old_dentry, 2738c2ecf20Sopenharmony_ci const struct path *new_parent, 2748c2ecf20Sopenharmony_ci struct dentry *new_dentry) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; 2778c2ecf20Sopenharmony_ci struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/** 2838c2ecf20Sopenharmony_ci * tomoyo_file_fcntl - Target for security_file_fcntl(). 2848c2ecf20Sopenharmony_ci * 2858c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 2868c2ecf20Sopenharmony_ci * @cmd: Command for fcntl(). 2878c2ecf20Sopenharmony_ci * @arg: Argument for @cmd. 2888c2ecf20Sopenharmony_ci * 2898c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_cistatic int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 2928c2ecf20Sopenharmony_ci unsigned long arg) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, 2978c2ecf20Sopenharmony_ci O_WRONLY | (arg & O_APPEND)); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci/** 3018c2ecf20Sopenharmony_ci * tomoyo_file_open - Target for security_file_open(). 3028c2ecf20Sopenharmony_ci * 3038c2ecf20Sopenharmony_ci * @f: Pointer to "struct file". 3048c2ecf20Sopenharmony_ci * @cred: Pointer to "struct cred". 3058c2ecf20Sopenharmony_ci * 3068c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_cistatic int tomoyo_file_open(struct file *f) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci /* Don't check read permission here if called from execve(). */ 3118c2ecf20Sopenharmony_ci if (current->in_execve) 3128c2ecf20Sopenharmony_ci return 0; 3138c2ecf20Sopenharmony_ci return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, 3148c2ecf20Sopenharmony_ci f->f_flags); 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci/** 3188c2ecf20Sopenharmony_ci * tomoyo_file_ioctl - Target for security_file_ioctl(). 3198c2ecf20Sopenharmony_ci * 3208c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 3218c2ecf20Sopenharmony_ci * @cmd: Command for ioctl(). 3228c2ecf20Sopenharmony_ci * @arg: Argument for @cmd. 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_cistatic int tomoyo_file_ioctl(struct file *file, unsigned int cmd, 3278c2ecf20Sopenharmony_ci unsigned long arg) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/** 3338c2ecf20Sopenharmony_ci * tomoyo_path_chmod - Target for security_path_chmod(). 3348c2ecf20Sopenharmony_ci * 3358c2ecf20Sopenharmony_ci * @path: Pointer to "struct path". 3368c2ecf20Sopenharmony_ci * @mode: DAC permission mode. 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_cistatic int tomoyo_path_chmod(const struct path *path, umode_t mode) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path, 3438c2ecf20Sopenharmony_ci mode & S_IALLUGO); 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/** 3478c2ecf20Sopenharmony_ci * tomoyo_path_chown - Target for security_path_chown(). 3488c2ecf20Sopenharmony_ci * 3498c2ecf20Sopenharmony_ci * @path: Pointer to "struct path". 3508c2ecf20Sopenharmony_ci * @uid: Owner ID. 3518c2ecf20Sopenharmony_ci * @gid: Group ID. 3528c2ecf20Sopenharmony_ci * 3538c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_cistatic int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci int error = 0; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (uid_valid(uid)) 3608c2ecf20Sopenharmony_ci error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, 3618c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, uid)); 3628c2ecf20Sopenharmony_ci if (!error && gid_valid(gid)) 3638c2ecf20Sopenharmony_ci error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, 3648c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, gid)); 3658c2ecf20Sopenharmony_ci return error; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci/** 3698c2ecf20Sopenharmony_ci * tomoyo_path_chroot - Target for security_path_chroot(). 3708c2ecf20Sopenharmony_ci * 3718c2ecf20Sopenharmony_ci * @path: Pointer to "struct path". 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3748c2ecf20Sopenharmony_ci */ 3758c2ecf20Sopenharmony_cistatic int tomoyo_path_chroot(const struct path *path) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/** 3818c2ecf20Sopenharmony_ci * tomoyo_sb_mount - Target for security_sb_mount(). 3828c2ecf20Sopenharmony_ci * 3838c2ecf20Sopenharmony_ci * @dev_name: Name of device file. Maybe NULL. 3848c2ecf20Sopenharmony_ci * @path: Pointer to "struct path". 3858c2ecf20Sopenharmony_ci * @type: Name of filesystem type. Maybe NULL. 3868c2ecf20Sopenharmony_ci * @flags: Mount options. 3878c2ecf20Sopenharmony_ci * @data: Optional data. Maybe NULL. 3888c2ecf20Sopenharmony_ci * 3898c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 3908c2ecf20Sopenharmony_ci */ 3918c2ecf20Sopenharmony_cistatic int tomoyo_sb_mount(const char *dev_name, const struct path *path, 3928c2ecf20Sopenharmony_ci const char *type, unsigned long flags, void *data) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci return tomoyo_mount_permission(dev_name, path, type, flags, data); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/** 3988c2ecf20Sopenharmony_ci * tomoyo_sb_umount - Target for security_sb_umount(). 3998c2ecf20Sopenharmony_ci * 4008c2ecf20Sopenharmony_ci * @mnt: Pointer to "struct vfsmount". 4018c2ecf20Sopenharmony_ci * @flags: Unmount options. 4028c2ecf20Sopenharmony_ci * 4038c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_cistatic int tomoyo_sb_umount(struct vfsmount *mnt, int flags) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci/** 4138c2ecf20Sopenharmony_ci * tomoyo_sb_pivotroot - Target for security_sb_pivotroot(). 4148c2ecf20Sopenharmony_ci * 4158c2ecf20Sopenharmony_ci * @old_path: Pointer to "struct path". 4168c2ecf20Sopenharmony_ci * @new_path: Pointer to "struct path". 4178c2ecf20Sopenharmony_ci * 4188c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_cistatic int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci/** 4268c2ecf20Sopenharmony_ci * tomoyo_socket_listen - Check permission for listen(). 4278c2ecf20Sopenharmony_ci * 4288c2ecf20Sopenharmony_ci * @sock: Pointer to "struct socket". 4298c2ecf20Sopenharmony_ci * @backlog: Backlog parameter. 4308c2ecf20Sopenharmony_ci * 4318c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4328c2ecf20Sopenharmony_ci */ 4338c2ecf20Sopenharmony_cistatic int tomoyo_socket_listen(struct socket *sock, int backlog) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci return tomoyo_socket_listen_permission(sock); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci/** 4398c2ecf20Sopenharmony_ci * tomoyo_socket_connect - Check permission for connect(). 4408c2ecf20Sopenharmony_ci * 4418c2ecf20Sopenharmony_ci * @sock: Pointer to "struct socket". 4428c2ecf20Sopenharmony_ci * @addr: Pointer to "struct sockaddr". 4438c2ecf20Sopenharmony_ci * @addr_len: Size of @addr. 4448c2ecf20Sopenharmony_ci * 4458c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_cistatic int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, 4488c2ecf20Sopenharmony_ci int addr_len) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci return tomoyo_socket_connect_permission(sock, addr, addr_len); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci/** 4548c2ecf20Sopenharmony_ci * tomoyo_socket_bind - Check permission for bind(). 4558c2ecf20Sopenharmony_ci * 4568c2ecf20Sopenharmony_ci * @sock: Pointer to "struct socket". 4578c2ecf20Sopenharmony_ci * @addr: Pointer to "struct sockaddr". 4588c2ecf20Sopenharmony_ci * @addr_len: Size of @addr. 4598c2ecf20Sopenharmony_ci * 4608c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_cistatic int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, 4638c2ecf20Sopenharmony_ci int addr_len) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci return tomoyo_socket_bind_permission(sock, addr, addr_len); 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci/** 4698c2ecf20Sopenharmony_ci * tomoyo_socket_sendmsg - Check permission for sendmsg(). 4708c2ecf20Sopenharmony_ci * 4718c2ecf20Sopenharmony_ci * @sock: Pointer to "struct socket". 4728c2ecf20Sopenharmony_ci * @msg: Pointer to "struct msghdr". 4738c2ecf20Sopenharmony_ci * @size: Size of message. 4748c2ecf20Sopenharmony_ci * 4758c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 4768c2ecf20Sopenharmony_ci */ 4778c2ecf20Sopenharmony_cistatic int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, 4788c2ecf20Sopenharmony_ci int size) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci return tomoyo_socket_sendmsg_permission(sock, msg, size); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistruct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = { 4848c2ecf20Sopenharmony_ci .lbs_task = sizeof(struct tomoyo_task), 4858c2ecf20Sopenharmony_ci}; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci/** 4888c2ecf20Sopenharmony_ci * tomoyo_task_alloc - Target for security_task_alloc(). 4898c2ecf20Sopenharmony_ci * 4908c2ecf20Sopenharmony_ci * @task: Pointer to "struct task_struct". 4918c2ecf20Sopenharmony_ci * @flags: clone() flags. 4928c2ecf20Sopenharmony_ci * 4938c2ecf20Sopenharmony_ci * Returns 0. 4948c2ecf20Sopenharmony_ci */ 4958c2ecf20Sopenharmony_cistatic int tomoyo_task_alloc(struct task_struct *task, 4968c2ecf20Sopenharmony_ci unsigned long clone_flags) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci struct tomoyo_task *old = tomoyo_task(current); 4998c2ecf20Sopenharmony_ci struct tomoyo_task *new = tomoyo_task(task); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci new->domain_info = old->domain_info; 5028c2ecf20Sopenharmony_ci atomic_inc(&new->domain_info->users); 5038c2ecf20Sopenharmony_ci new->old_domain_info = NULL; 5048c2ecf20Sopenharmony_ci return 0; 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/** 5088c2ecf20Sopenharmony_ci * tomoyo_task_free - Target for security_task_free(). 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * @task: Pointer to "struct task_struct". 5118c2ecf20Sopenharmony_ci */ 5128c2ecf20Sopenharmony_cistatic void tomoyo_task_free(struct task_struct *task) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(task); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci if (s->domain_info) { 5178c2ecf20Sopenharmony_ci atomic_dec(&s->domain_info->users); 5188c2ecf20Sopenharmony_ci s->domain_info = NULL; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci if (s->old_domain_info) { 5218c2ecf20Sopenharmony_ci atomic_dec(&s->old_domain_info->users); 5228c2ecf20Sopenharmony_ci s->old_domain_info = NULL; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci/* 5278c2ecf20Sopenharmony_ci * tomoyo_security_ops is a "struct security_operations" which is used for 5288c2ecf20Sopenharmony_ci * registering TOMOYO. 5298c2ecf20Sopenharmony_ci */ 5308c2ecf20Sopenharmony_cistatic struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { 5318c2ecf20Sopenharmony_ci LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), 5328c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), 5338c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), 5348c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_free, tomoyo_task_free), 5358c2ecf20Sopenharmony_ci#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER 5368c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec), 5378c2ecf20Sopenharmony_ci#endif 5388c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), 5398c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), 5408c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_open, tomoyo_file_open), 5418c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate), 5428c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink), 5438c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir), 5448c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir), 5458c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink), 5468c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod), 5478c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_link, tomoyo_path_link), 5488c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_rename, tomoyo_path_rename), 5498c2ecf20Sopenharmony_ci LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr), 5508c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl), 5518c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl), 5528c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), 5538c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_chown, tomoyo_path_chown), 5548c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), 5558c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount), 5568c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount), 5578c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot), 5588c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind), 5598c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect), 5608c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen), 5618c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg), 5628c2ecf20Sopenharmony_ci}; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci/* Lock for GC. */ 5658c2ecf20Sopenharmony_ciDEFINE_SRCU(tomoyo_ss); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ciint tomoyo_enabled __lsm_ro_after_init = 1; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci/** 5708c2ecf20Sopenharmony_ci * tomoyo_init - Register TOMOYO Linux as a LSM module. 5718c2ecf20Sopenharmony_ci * 5728c2ecf20Sopenharmony_ci * Returns 0. 5738c2ecf20Sopenharmony_ci */ 5748c2ecf20Sopenharmony_cistatic int __init tomoyo_init(void) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci struct tomoyo_task *s = tomoyo_task(current); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci /* register ourselves with the security framework */ 5798c2ecf20Sopenharmony_ci security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); 5808c2ecf20Sopenharmony_ci pr_info("TOMOYO Linux initialized\n"); 5818c2ecf20Sopenharmony_ci s->domain_info = &tomoyo_kernel_domain; 5828c2ecf20Sopenharmony_ci atomic_inc(&tomoyo_kernel_domain.users); 5838c2ecf20Sopenharmony_ci s->old_domain_info = NULL; 5848c2ecf20Sopenharmony_ci tomoyo_mm_init(); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci return 0; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ciDEFINE_LSM(tomoyo) = { 5908c2ecf20Sopenharmony_ci .name = "tomoyo", 5918c2ecf20Sopenharmony_ci .enabled = &tomoyo_enabled, 5928c2ecf20Sopenharmony_ci .flags = LSM_FLAG_LEGACY_MAJOR, 5938c2ecf20Sopenharmony_ci .blobs = &tomoyo_blob_sizes, 5948c2ecf20Sopenharmony_ci .init = tomoyo_init, 5958c2ecf20Sopenharmony_ci}; 596