Skip to content

Commit 1dc4c22

Browse files
HorlogeSkynetstgraber
authored andcommitted
proc: checks system security policy before trying to get personalities
096972f and fc8f593 introduces task personalities retrieval to fix incorrect /proc files info in some cases. Linux governs access to personalities based on system ptrace policy, which may be restricted by an LSM (e.g. Yama). This patch implements a simple check for init's personality access to make sure ptrace usage is allowed, and prevent access from containers to proc files with "Permission denied" error if not. > closes #636 (follow-up to #553 and #609). Signed-off-by: Samuel FORESTIER <[email protected]>
1 parent cef6232 commit 1dc4c22

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

src/proc_fuse.c

+12-3
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,11 @@ __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
145145
strcmp(path, "/proc/swaps") == 0 ||
146146
strcmp(path, "/proc/loadavg") == 0 ||
147147
strcmp(path, "/proc/slabinfo") == 0) {
148-
if (liblxcfs_functional())
148+
if (liblxcfs_functional()) {
149+
if (!can_access_personality())
150+
return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY);
149151
sb->st_size = get_procfile_size_with_personality(path);
152+
}
150153
else
151154
sb->st_size = get_procfile_size(path);
152155
sb->st_mode = S_IFREG | 00444;
@@ -206,8 +209,11 @@ __lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi)
206209

207210
info->type = type;
208211

209-
if (liblxcfs_functional())
212+
if (liblxcfs_functional()) {
213+
if (!can_access_personality())
214+
return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY);
210215
info->buflen = get_procfile_size_with_personality(path) + BUF_RESERVE_SIZE;
216+
}
211217
else
212218
info->buflen = get_procfile_size(path) + BUF_RESERVE_SIZE;
213219

@@ -1646,8 +1652,11 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
16461652
return read_file_fuse_with_offset(LXC_TYPE_PROC_MEMINFO_PATH,
16471653
buf, size, offset, f);
16481654
case LXC_TYPE_PROC_CPUINFO:
1649-
if (liblxcfs_functional())
1655+
if (liblxcfs_functional()) {
1656+
if (!can_access_personality())
1657+
return log_error(-EACCES, RESTRICTED_PERSONALITY_ACCESS_POLICY);
16501658
return proc_read_with_personality(&proc_cpuinfo_read, buf, size, offset, fi);
1659+
}
16511660

16521661
return read_file_fuse_with_offset(LXC_TYPE_PROC_CPUINFO_PATH,
16531662
buf, size, offset, f);

src/utils.c

+23-1
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,31 @@ int get_task_personality(pid_t pid, __u32 *personality)
685685
ret = read_nointr(fd, buf, sizeof(buf) - 1);
686686
if (ret >= 0) {
687687
buf[ret] = '\0';
688-
if (safe_uint32(buf, personality, 16) < 0)
688+
if (personality != NULL && safe_uint32(buf, personality, 16) < 0)
689689
return log_error(-1, "Failed to convert personality %s", buf);
690690
}
691691

692692
return ret;
693693
}
694+
695+
/*
696+
This function checks whether system security policy (i.e. Yama LSM) allows personality access, by trying on
697+
init own one.
698+
This is required as it may be restricted by a ptrace access mode check (see PROC(5)), and
699+
`get_task_personality` function relies on this.
700+
*/
701+
bool can_access_personality(void)
702+
{
703+
static int could_access_init_personality = -1;
704+
705+
/* init personality has never been accessed (cache is empty) */
706+
if (could_access_init_personality == -1) {
707+
if (get_task_personality(1, NULL) < 0) {
708+
could_access_init_personality = 0;
709+
} else {
710+
could_access_init_personality = 1;
711+
}
712+
}
713+
714+
return could_access_init_personality != 0;
715+
}

src/utils.h

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#define SEND_CREDS_NOTSK 1
2626
#define SEND_CREDS_FAIL 2
2727

28+
#define RESTRICTED_PERSONALITY_ACCESS_POLICY "Due to restricted personality access policy, reading proc files from containers is not permitted"
29+
2830
struct file_info;
2931

3032
__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)
7779
extern char *read_file_at(int dfd, const char *fnam, unsigned int o_flags);
7880

7981
extern int get_task_personality(pid_t pid, __u32 *personality);
82+
extern bool can_access_personality(void);
8083
extern int get_host_personality(__u32 *personality);
8184

8285
#endif /* __LXCFS_UTILS_H */

0 commit comments

Comments
 (0)