📄 hooks.c
字号:
&newsid); if (rc) { printk(KERN_WARNING "%s: " "security_transition_sid failed, rc=%d (dev=%s " "ino=%ld)\n", __FUNCTION__, -rc, inode->i_sb->s_id, inode->i_ino); return rc; } } /* Possibly defer initialization to selinux_complete_init. */ if (sbsec->initialized) { struct inode_security_struct *isec = inode->i_security; isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sid = newsid; isec->initialized = 1; } if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) return -EOPNOTSUPP; if (name) { namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); if (!namep) return -ENOMEM; *name = namep; } if (value && len) { rc = security_sid_to_context(newsid, &context, &clen); if (rc) { kfree(namep); return rc; } *value = context; *len = clen; } return 0;}static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask){ return may_create(dir, dentry, SECCLASS_FILE);}static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry){ int rc; rc = secondary_ops->inode_link(old_dentry,dir,new_dentry); if (rc) return rc; return may_link(dir, old_dentry, MAY_LINK);}static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry){ int rc; rc = secondary_ops->inode_unlink(dir, dentry); if (rc) return rc; return may_link(dir, dentry, MAY_UNLINK);}static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name){ return may_create(dir, dentry, SECCLASS_LNK_FILE);}static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask){ return may_create(dir, dentry, SECCLASS_DIR);}static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry){ return may_link(dir, dentry, MAY_RMDIR);}static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev){ int rc; 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 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 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);}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_FORCE) return 0; 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_setotherxattr(struct dentry *dentry, char *name){ if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof XATTR_SECURITY_PREFIX - 1)) { if (!strcmp(name, XATTR_NAME_CAPS)) { if (!capable(CAP_SETFCAP)) return -EPERM; } else if (!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);}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)) return selinux_inode_setotherxattr(dentry, name); sbsec = inode->i_sb->s_security; if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) return -EOPNOTSUPP; if (!is_owner_or_cap(inode)) return -EPERM; AVC_AUDIT_DATA_INIT(&ad,FS); ad.u.fs.dentry = dentry; rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, FILE__RELABELFROM, &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, &ad); if (rc) return rc; rc = security_validate_transition(isec->sid, newsid, tsec->sid, isec->sclass); if (rc) return rc; return avc_has_perm(newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, &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){ 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)) return selinux_inode_setotherxattr(dentry, name); /* No one is allowed to remove a SELinux security label. You can change the label, but all data must be labeled. */ return -EACCES;}/* * Copy the in-core inode security context value to the user. If the * getxattr() prior to this succeeded, check to see if we need to * canonicalize the value to be finally returned to the user. * * Permission check is handled by selinux_inode_getxattr hook. */static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err){ struct inode_security_struct *isec = inode->i_security; if (strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; return selinux_getsecurity(isec->sid, buffer, size);}static int selinux_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags){ 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 inode *inode, char *buffer, size_t buffer_size){ const int len = sizeof(XATTR_NAME_SELINUX); if (buffer && len <= buffer_size) memcpy(buffer, XATTR_NAME_SELINUX, len); return len;}static int selinux_inode_need_killpriv(struct dentry *dentry){ return secondary_ops->inode_need_killpriv(dentry);}static int selinux_inode_killpriv(struct dentry *dentry){ return secondary_ops->inode_killpriv(dentry);}/* file security operations */static int selinux_revalidate_file_permission(struct file *file, int mask){ int rc; struct inode *inode = file->f_path.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; rc = file_has_perm(current, file, file_mask_to_av(inode->i_mode, mask)); if (rc) return rc; return selinux_netlbl_inode_permission(inode, mask);}static int selinux_file_permission(struct file *file, int mask){ struct inode *inode = file->f_path.dentry->d_inode; struct task_security_struct *tsec = current->security; struct file_security_struct *fsec = file->f_security; struct inode_security_struct *isec = inode->i_security; if (!mask) { /* No permission to check. Existence test. */ return 0; } if (tsec->sid == fsec->sid && fsec->isid == isec->sid && fsec->pseqno == avc_policy_seqno()) return selinux_netlbl_inode_permission(inode, mask); return selinux_revalidate_file_permission(file, 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){#ifndef CONFIG_PPC32 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { /* * We are making executable an anonymous mapping or a * private file mapping that will also be writable. * This has an additional check. */ int rc = task_has_perm(current, current, PROCESS__EXECMEM); if (rc) return rc; }#endif 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 reqprot, unsigned long prot, unsigned long flags, unsigned long addr, unsigned long addr_only){ int rc = 0; u32 sid = ((struct task_security_struct*)(current->security))->sid; if (addr < mmap_min_addr) rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, NULL); if (rc || addr_only) return rc; if (selinux_checkreqprot) prot = reqprot; return file_map_prot_check(file, prot, (flags & MAP_TYPE) == MAP_SHARED);}static int selinux_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot){ int rc; rc = secondary_ops->file_mprotect(vma, reqprot, prot); if (rc) return rc; if (selinux_checkreqprot) prot = reqprot;#ifndef CONFIG_PPC32 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { rc = 0; if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { rc = task_has_perm(current, current, PROCESS__EXECHEAP); } else if (!vma->vm_file && vma->vm_start <= vma->vm_mm->start_stack && vma->vm_end >= vma->vm_mm->start_stack) { rc = task_has_perm(current, current, PROCESS__EXECSTACK); } else if (vma->vm_file && vma->anon_vma) { /* * We are making executable a file mapping that has * had some COW done. Since pages might have been * written, check ability to execute the possibly * modified content. This typically should only * occur for text relocations. */ rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD); } if (rc) return rc; }#endif 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_path.dentry || !file->f_path.dentry->d_inode) { err = -EINVAL; break; } if ((file->f_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -