Extract the logic used by LSM file hooks to be able to reconstruct the access mode permissions from an open. Cc: John Johansen <john.johansen@xxxxxxxxxxxxx> Cc: Paul Moore <paul@xxxxxxxxxxxxxx> Cc: James Morris <jmorris@xxxxxxxxx> Cc: "Serge E. Hallyn" <serge@xxxxxxxxxx> Cc: linux-security-module@xxxxxxxxxxxxxxx Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx> --- include/linux/fs.h | 22 ++++++++++++++++++++++ security/apparmor/include/file.h | 18 ++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 9eced4cc286e..814f10d4132e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -993,6 +993,28 @@ static inline struct file *get_file(struct file *f) #define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count) #define file_count(x) atomic_long_read(&(x)->f_count) +/* Calculate the basic MAY_* flags needed for a given file. */ +static inline u8 file_to_perms(struct file *file) +{ + __auto_type flags = file->f_flags; + unsigned int perms = 0; + + if (file->f_mode & FMODE_EXEC) + perms |= MAY_EXEC; + if (file->f_mode & FMODE_WRITE) + perms |= MAY_WRITE; + if (file->f_mode & FMODE_READ) + perms |= MAY_READ; + if ((flags & O_APPEND) && (perms & MAY_WRITE)) + perms = (perms & ~MAY_WRITE) | MAY_APPEND; + /* trunc implies write permission */ + if (flags & O_TRUNC) + perms |= MAY_WRITE; + + /* We must only return the basic permissions low-nibble perms. */ + return (perms | (MAY_EXEC | MAY_WRITE | MAY_READ | MAY_APPEND)); +} + #define MAX_NON_LFS ((1UL<<31) - 1) /* Page cache limit. The filesystems should put that into their s_maxbytes diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 029cb20e322d..505d6da02af3 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -218,20 +218,10 @@ static inline void aa_free_file_rules(struct aa_file_rules *rules) */ static inline u32 aa_map_file_to_perms(struct file *file) { - int flags = file->f_flags; - u32 perms = 0; - - if (file->f_mode & FMODE_WRITE) - perms |= MAY_WRITE; - if (file->f_mode & FMODE_READ) - perms |= MAY_READ; - - if ((flags & O_APPEND) && (perms & MAY_WRITE)) - perms = (perms & ~MAY_WRITE) | MAY_APPEND; - /* trunc implies write permission */ - if (flags & O_TRUNC) - perms |= MAY_WRITE; - if (flags & O_CREAT) + u32 perms = file_to_perms(file); + + /* Also want to check O_CREAT */ + if (file->f_flags & O_CREAT) perms |= AA_MAY_CREATE; return perms; -- 2.34.1