📄 hooks.c
字号:
rc = secondary_ops->inode_mknod(dir, dentry, mode, dev); if (rc) return rc; return may_create(dir, dentry, inode_mode_to_security_class(mode));}static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev){ post_create(dir, dentry);}static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry){ return may_rename(old_inode, old_dentry, new_inode, new_dentry);}static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry){ return;}static int selinux_inode_readlink(struct dentry *dentry){ return dentry_has_perm(current, NULL, dentry, FILE__READ);}static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata){ int rc; rc = secondary_ops->inode_follow_link(dentry,nameidata); if (rc) return rc; return dentry_has_perm(current, NULL, dentry, FILE__READ);}static int selinux_inode_permission(struct inode *inode, int mask, struct nameidata *nd){ int rc; rc = secondary_ops->inode_permission(inode, mask, nd); if (rc) return rc; if (!mask) { /* No permission to check. Existence test. */ return 0; } return inode_has_perm(current, inode, file_mask_to_av(inode->i_mode, mask), NULL, NULL);}static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr){ int rc; rc = secondary_ops->inode_setattr(dentry, iattr); if (rc) return rc; if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME_SET | ATTR_MTIME_SET)) return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); return dentry_has_perm(current, NULL, dentry, FILE__WRITE);}static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry){ return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);}static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags){ struct task_security_struct *tsec = current->security; struct inode *inode = dentry->d_inode; struct inode_security_struct *isec = inode->i_security; struct superblock_security_struct *sbsec; struct avc_audit_data ad; u32 newsid; int rc = 0; if (strcmp(name, XATTR_NAME_SELINUX)) { if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof XATTR_SECURITY_PREFIX - 1) && !capable(CAP_SYS_ADMIN)) { /* A different attribute in the security namespace. Restrict to administrator. */ return -EPERM; } /* Not an attribute we recognize, so just check the ordinary setattr permission. */ return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); } sbsec = inode->i_sb->s_security; if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) return -EOPNOTSUPP; AVC_AUDIT_DATA_INIT(&ad,FS); ad.u.fs.dentry = dentry; rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, FILE__RELABELFROM, &isec->avcr, &ad); if (rc) return rc; rc = security_context_to_sid(value, size, &newsid); if (rc) return rc; rc = avc_has_perm(tsec->sid, newsid, isec->sclass, FILE__RELABELTO, NULL, &ad); if (rc) return rc; return avc_has_perm(newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, NULL, &ad);}static void selinux_inode_post_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags){ struct inode *inode = dentry->d_inode; struct inode_security_struct *isec = inode->i_security; u32 newsid; int rc; if (strcmp(name, XATTR_NAME_SELINUX)) { /* Not an attribute we recognize, so nothing to do. */ return; } rc = security_context_to_sid(value, size, &newsid); if (rc) { printk(KERN_WARNING "%s: unable to obtain SID for context " "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc); return; } isec->sid = newsid; return;}static int selinux_inode_getxattr (struct dentry *dentry, char *name){ struct inode *inode = dentry->d_inode; struct superblock_security_struct *sbsec = inode->i_sb->s_security; if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) return -EOPNOTSUPP; return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);}static int selinux_inode_listxattr (struct dentry *dentry){ return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);}static int selinux_inode_removexattr (struct dentry *dentry, char *name){ if (strcmp(name, XATTR_NAME_SELINUX)) { if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof XATTR_SECURITY_PREFIX - 1) && !capable(CAP_SYS_ADMIN)) { /* A different attribute in the security namespace. Restrict to administrator. */ return -EPERM; } /* Not an attribute we recognize, so just check the ordinary setattr permission. Might want a separate permission for removexattr. */ return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); } /* No one is allowed to remove a SELinux security label. You can change the label, but all data must be labeled. */ return -EACCES;}static int selinux_inode_getsecurity(struct dentry *dentry, const char *name, void *buffer, size_t size){ struct inode *inode = dentry->d_inode; struct inode_security_struct *isec = inode->i_security; char *context; unsigned len; int rc; /* Permission check handled by selinux_inode_getxattr hook.*/ if (strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; rc = security_sid_to_context(isec->sid, &context, &len); if (rc) return rc; if (!buffer || !size) { kfree(context); return len; } if (size < len) { kfree(context); return -ERANGE; } memcpy(buffer, context, len); kfree(context); return len;}static int selinux_inode_setsecurity(struct dentry *dentry, const char *name, const void *value, size_t size, int flags){ struct inode *inode = dentry->d_inode; struct inode_security_struct *isec = inode->i_security; u32 newsid; int rc; if (strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; if (!value || !size) return -EACCES; rc = security_context_to_sid((void*)value, size, &newsid); if (rc) return rc; isec->sid = newsid; return 0;}static int selinux_inode_listsecurity(struct dentry *dentry, char *buffer){ const int len = sizeof(XATTR_NAME_SELINUX); if (buffer) memcpy(buffer, XATTR_NAME_SELINUX, len); return len;}/* file security operations */static int selinux_file_permission(struct file *file, int mask){ struct inode *inode = file->f_dentry->d_inode; if (!mask) { /* No permission to check. Existence test. */ return 0; } /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) mask |= MAY_APPEND; return file_has_perm(current, file, file_mask_to_av(inode->i_mode, mask));}static int selinux_file_alloc_security(struct file *file){ return file_alloc_security(file);}static void selinux_file_free_security(struct file *file){ file_free_security(file);}static int selinux_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ int error = 0; switch (cmd) { case FIONREAD: /* fall through */ case FIBMAP: /* fall through */ case FIGETBSZ: /* fall through */ case EXT2_IOC_GETFLAGS: /* fall through */ case EXT2_IOC_GETVERSION: error = file_has_perm(current, file, FILE__GETATTR); break; case EXT2_IOC_SETFLAGS: /* fall through */ case EXT2_IOC_SETVERSION: error = file_has_perm(current, file, FILE__SETATTR); break; /* sys_ioctl() checks */ case FIONBIO: /* fall through */ case FIOASYNC: error = file_has_perm(current, file, 0); break; case KDSKBENT: case KDSKBSENT: error = task_has_capability(current,CAP_SYS_TTY_CONFIG); break; /* default case assumes that the command will go * to the file's ioctl() function. */ default: error = file_has_perm(current, file, FILE__IOCTL); } return error;}static int file_map_prot_check(struct file *file, unsigned long prot, int shared){ if (file) { /* read access is always possible with a mapping */ u32 av = FILE__READ; /* write access only matters if the mapping is shared */ if (shared && (prot & PROT_WRITE)) av |= FILE__WRITE; if (prot & PROT_EXEC) av |= FILE__EXECUTE; return file_has_perm(current, file, av); } return 0;}static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags){ int rc; rc = secondary_ops->file_mmap(file, prot, flags); if (rc) return rc; return file_map_prot_check(file, prot, (flags & MAP_TYPE) == MAP_SHARED);}static int selinux_file_mprotect(struct vm_area_struct *vma, unsigned long prot){ int rc; rc = secondary_ops->file_mprotect(vma, prot); if (rc) return rc; return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);}static int selinux_file_lock(struct file *file, unsigned int cmd){ return file_has_perm(current, file, FILE__LOCK);}static int selinux_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg){ int err = 0; switch (cmd) { case F_SETFL: if (!file->f_dentry || !file->f_dentry->d_inode) { err = -EINVAL; break; } if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) { err = file_has_perm(current, file,FILE__WRITE); break; } /* fall through */ case F_SETOWN: case F_SETSIG: case F_GETFL: case F_GETOWN: case F_GETSIG: /* Just check FD__USE permission */ err = file_has_perm(current, file, 0); break; case F_GETLK: case F_SETLK: case F_SETLKW:#if BITS_PER_LONG == 32 case F_GETLK64: case F_SETLK64: case F_SETLKW64:#endif if (!file->f_dentry || !file->f_dentry->d_inode) { err = -EINVAL; break; } err = file_has_perm(current, file, FILE__LOCK); break; } return err;}static int selinux_file_set_fowner(struct file *file){ struct task_security_struct *tsec; struct file_security_struct *fsec; tsec = current->security; fsec = file->f_security; fsec->fown_sid = tsec->sid; return 0;}static int selinux_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason){ struct file *file; u32 perm; struct task_security_struct *tsec; struct file_security_struct *fsec; /* struct fown_struct is never outside the context of a struct file */ file = (struct file *)((long)fown - offsetof(struct file,f_owner)); tsec = tsk->security; fsec = file->f_security; if (!fown->signum) perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */ else perm = signal_to_av(fown->signum); return avc_has_perm(fsec->fown_sid, tsec->sid, SECCLASS_PROCESS, perm, NULL, NULL);}static int selinux_file_receive(struct file *file){ return file_has_perm(current, file, file_to_av(file));}/* task security operations */static int selinux_task_create(unsigned long clone_flags){ int rc; rc = secondary_ops->task_create(clone_flags); if (rc) return rc; return task_has_perm(current, current, PROCESS__FORK);}static int selinux_task_alloc_security(struct task_struct *tsk){ struct task_security_struct *tsec1, *tsec2; int rc; tsec1 = current->security; rc = task_alloc_security(tsk); if (rc) return rc; tsec2 = tsk->security; tsec2->osid = tsec1->osid; tsec2->sid = tsec1->sid; /* Retain the exec and create SIDs across fork */ tsec2->exec_sid = tsec1->exec_sid; tsec2->create_sid = tsec1->create_sid; /* Retain ptracer SID across fork, if any. This will be reset by the ptrace hook upon any subsequent ptrace_attach operations. */ tsec2->ptrace_sid = tsec1->ptrace_sid; return 0;}static void selinux_task_free_security(struct task_struct *tsk){ task_free_security(tsk);}static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags){ /* Since setuid only affects the current process, and since the SELinux controls are not based on the Linux identity attributes, SELinux does not need to control this operation. However, SELinux does control the use of the CAP_SETUID and CAP_SETGID capabilities using the capable hook. */ return 0;}static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags){ return secondary_ops->task_post_setuid(id0,id1,id2,flags);}static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags){ /* See the comment for setuid above. */ return 0;}static int selinux_task_setpgid(struct task_struct *p, pid_t pgid){ return task_has_perm(current, p, PROCESS__SETPGID);}static int selinux_task_getpgid(struct task_struct *p){ return task_ha
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -