From 27ded8954a1235bb65ffc9c730ae5a50b1dfed61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20M=C3=B6llers?= Date: Fri, 29 May 2020 14:35:43 +0000 Subject: [PATCH] pam_setquota: skip mountpoints equal to the user's $HOME MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Matthias Gerstner found the following issue: So this pam_setquota module iterates over all mounted file systems using `setmntent()` and `getmntent()`. It tries to find the longest match of a file system mounted on /home/$USER or above (except when the fs=/some/path parameter is passed to the pam module). The thing is that /home/$USER is owned by the unprivileged user. And there exist tools like fusermount from libfuse which is by default installed setuid-root for everybody. fusermount allows to mount a FUSE file system using an arbitrary "source device name" as the unprivileged user. Thus considering the following use case: 1) there is only the root file system (/) or a file system is mounted on /home, but not on /home/$USER. 2) the attacker mounts a fake FUSE file system over its own home directory: ``` user $ export _FUSE_COMMFD=0 user $ fusermount $HOME -ononempty,fsname=/dev/sda1 ``` This will result in a mount entry in /proc/mounts looking like this: ``` /dev/sda1 on /home/$USER type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=100) ``` 3) when the attacker now logs in with pam_setquota configured then pam_setquota will identify /dev/sda1 and the file system where to apply the user's quota on. As a result an unprivileged user has full control over onto which block device the quota is applied. If the user's $HOME is on a separate partition, setting a quota on the user's $HOME does not really make sense, so this patch skips mountpoints equal to the user's $HOME, preventing the above mentioned bug as a side-effect (or vice-versa). Reported-by: Matthias Gerstner Co-authored-by: Tomáš Mráz Co-authored-by: Dmitry V. Levin Resolves: https://github.com/linux-pam/linux-pam/pull/230 --- modules/pam_setquota/pam_setquota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pam_setquota/pam_setquota.c b/modules/pam_setquota/pam_setquota.c index 9c05862a..01b05e38 100644 --- a/modules/pam_setquota/pam_setquota.c +++ b/modules/pam_setquota/pam_setquota.c @@ -275,7 +275,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, */ if ((mnt_len > match_size || (mnt_len == 0 && mnt->mnt_dir[0] == '/')) && (s = pam_str_skip_prefix_len(pwd->pw_dir, mnt->mnt_dir, mnt_len)) != NULL && - (s[0] == '\0' || s[0] == '/')) { + s[0] == '/') { free(mntdevice); if ((mntdevice = strdup(mnt->mnt_fsname)) == NULL) { pam_syslog(pamh, LOG_CRIT, "Memory allocation error");