diff --git a/src/proc_fuse.c b/src/proc_fuse.c index 1049e72d..f48c40b1 100644 --- a/src/proc_fuse.c +++ b/src/proc_fuse.c @@ -145,8 +145,11 @@ __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb) strcmp(path, "/proc/swaps") == 0 || strcmp(path, "/proc/loadavg") == 0 || strcmp(path, "/proc/slabinfo") == 0) { - if (liblxcfs_functional()) + if (liblxcfs_functional()) { + if (!can_access_personality()) + return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY); sb->st_size = get_procfile_size_with_personality(path); + } else sb->st_size = get_procfile_size(path); sb->st_mode = S_IFREG | 00444; @@ -206,8 +209,11 @@ __lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi) info->type = type; - if (liblxcfs_functional()) + if (liblxcfs_functional()) { + if (!can_access_personality()) + return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY); info->buflen = get_procfile_size_with_personality(path) + BUF_RESERVE_SIZE; + } else info->buflen = get_procfile_size(path) + BUF_RESERVE_SIZE; @@ -1646,8 +1652,11 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size, return read_file_fuse_with_offset(LXC_TYPE_PROC_MEMINFO_PATH, buf, size, offset, f); case LXC_TYPE_PROC_CPUINFO: - if (liblxcfs_functional()) + if (liblxcfs_functional()) { + if (!can_access_personality()) + return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY); return proc_read_with_personality(&proc_cpuinfo_read, buf, size, offset, fi); + } return read_file_fuse_with_offset(LXC_TYPE_PROC_CPUINFO_PATH, buf, size, offset, f); diff --git a/src/utils.c b/src/utils.c index ab665f74..deae03fb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -685,9 +685,31 @@ int get_task_personality(pid_t pid, __u32 *personality) ret = read_nointr(fd, buf, sizeof(buf) - 1); if (ret >= 0) { buf[ret] = '\0'; - if (safe_uint32(buf, personality, 16) < 0) + if (personality != NULL && safe_uint32(buf, personality, 16) < 0) return log_error(-1, "Failed to convert personality %s", buf); } return ret; } + +/* + This function checks whether system security policy (i.e. Yama LSM) allows personality access, by trying on + init own one. + This is required as it may be restricted by a ptrace access mode check (see PROC(5)), and + `get_task_personality` function relies on this. +*/ +bool can_access_personality(void) +{ + static int could_access_init_personality = -1; + + /* init personality has never been accessed (cache is empty) */ + if (could_access_init_personality == -1) { + if (get_task_personality(1, NULL) < 0) { + could_access_init_personality = 0; + } else { + could_access_init_personality = 1; + } + } + + return could_access_init_personality != 0; +} diff --git a/src/utils.h b/src/utils.h index 7ed021a9..90701ced 100644 --- a/src/utils.h +++ b/src/utils.h @@ -25,6 +25,8 @@ #define SEND_CREDS_NOTSK 1 #define SEND_CREDS_FAIL 2 +#define RESTRICTED_PERSONALITY_ACCESS_POLICY "Due to restricted personality access policy, reading proc files from containers is not permitted" + struct file_info; __attribute__((__format__(__printf__, 4, 5))) extern char *must_strcat(char **src, size_t *sz, size_t *asz, const char *format, ...); @@ -77,6 +79,7 @@ static inline bool file_exists(const char *f) extern char *read_file_at(int dfd, const char *fnam, unsigned int o_flags); extern int get_task_personality(pid_t pid, __u32 *personality); +extern bool can_access_personality(void); extern int get_host_personality(__u32 *personality); #endif /* __LXCFS_UTILS_H */