Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
util-linux.34260
util-linux-libmount-check-fuse-umount-CVE-2021-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File util-linux-libmount-check-fuse-umount-CVE-2021-3995.patch of Package util-linux.34260
Includes backport of ul_strtou64(). From f3db9bd609494099f0c1b95231c5dfe383346929 Mon Sep 17 00:00:00 2001 From: Karel Zak <kzak@redhat.com> Date: Wed, 24 Nov 2021 13:53:25 +0100 Subject: [PATCH 1/2] libmount: fix UID check for FUSE umount [CVE-2021-3995] Improper UID check allows an unprivileged user to unmount FUSE filesystems of users with similar UID. Signed-off-by: Karel Zak <kzak@redhat.com> --- include/strutils.h | 2 +- libmount/src/context_umount.c | 14 +++--------- libmount/src/mountP.h | 1 + libmount/src/optstr.c | 42 +++++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 12 deletions(-) Index: util-linux-2.36.2/include/strutils.h =================================================================== --- util-linux-2.36.2.orig/include/strutils.h +++ util-linux-2.36.2/include/strutils.h @@ -88,8 +88,8 @@ static inline char *mem2strcpy(char *des if (n + 1 > nmax) n = nmax - 1; + memset(dest, '\0', nmax); memcpy(dest, src, n); - dest[nmax-1] = '\0'; return dest; } Index: util-linux-2.36.2/libmount/src/context_umount.c =================================================================== --- util-linux-2.36.2.orig/libmount/src/context_umount.c +++ util-linux-2.36.2/libmount/src/context_umount.c @@ -447,10 +447,7 @@ static int is_fuse_usermount(struct libm struct libmnt_ns *ns_old; const char *type = mnt_fs_get_fstype(cxt->fs); const char *optstr; - char *user_id = NULL; - size_t sz; - uid_t uid; - char uidstr[sizeof(stringify_value(ULONG_MAX))]; + uid_t uid, entry_uid; *errsv = 0; @@ -467,11 +464,7 @@ static int is_fuse_usermount(struct libm optstr = mnt_fs_get_fs_options(cxt->fs); if (!optstr) return 0; - - if (mnt_optstr_get_option(optstr, "user_id", &user_id, &sz) != 0) - return 0; - - if (sz == 0 || user_id == NULL) + if (mnt_optstr_get_uid(optstr, "user_id", &entry_uid) != 0) return 0; /* get current user */ @@ -488,8 +481,7 @@ static int is_fuse_usermount(struct libm return 0; } - snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long) uid); - return strncmp(user_id, uidstr, sz) == 0; + return uid == entry_uid; } /* Index: util-linux-2.36.2/libmount/src/mountP.h =================================================================== --- util-linux-2.36.2.orig/libmount/src/mountP.h +++ util-linux-2.36.2/libmount/src/mountP.h @@ -401,6 +401,7 @@ extern const struct libmnt_optmap *mnt_o const struct libmnt_optmap **mapent); /* optstr.c */ +extern int mnt_optstr_get_uid(const char *optstr, const char *name, uid_t *uid); extern int mnt_optstr_remove_option_at(char **optstr, char *begin, char *end); extern int mnt_optstr_fix_gid(char **optstr, char *value, size_t valsz, char **next); extern int mnt_optstr_fix_uid(char **optstr, char *value, size_t valsz, char **next); Index: util-linux-2.36.2/libmount/src/optstr.c =================================================================== --- util-linux-2.36.2.orig/libmount/src/optstr.c +++ util-linux-2.36.2/libmount/src/optstr.c @@ -44,6 +44,31 @@ struct libmnt_optloc { #define mnt_optmap_entry_novalue(e) \ (e && (e)->name && !strchr((e)->name, '=') && !((e)->mask & MNT_PREFIX)) +static int ul_strtou64(const char *str, uint64_t *num, int base) +{ + char *end = NULL; + int64_t tmp; + + errno = 0; + if (str == NULL || *str == '\0') + return -EINVAL; + + /* we need to ignore negative numbers, note that for invalid negative + * number strtoimax() returns negative number too, so we do not + * need to check errno here */ + tmp = (int64_t) strtoimax(str, &end, base); + if (tmp < 0) + errno = ERANGE; + else { + errno = 0; + *num = strtoumax(str, &end, base); + } + + if (errno || str == end || (end && *end)) + return -EINVAL; + return 0; +} + /* * Parses the first option from @optstr. The @optstr pointer is set to the beginning * of the next option. @@ -1090,6 +1115,48 @@ int mnt_optstr_fix_user(char **optstr) return rc; } +/* + * Converts value from @optstr addressed by @name to uid. + * + * Returns: 0 on success, 1 if not found, <0 on error + */ +int mnt_optstr_get_uid(const char *optstr, const char *name, uid_t *uid) +{ + char *value = NULL; + size_t valsz = 0; + char buf[sizeof(stringify_value(UINT64_MAX))]; + int rc; + uint64_t num; + + assert(optstr); + assert(name); + assert(uid); + + rc = mnt_optstr_get_option(optstr, name, &value, &valsz); + if (rc != 0) + goto fail; + + if (valsz > sizeof(buf) - 1) { + rc = -ERANGE; + goto fail; + } + mem2strcpy(buf, value, valsz, sizeof(buf)); + + rc = ul_strtou64(buf, &num, 10); + if (rc != 0) + goto fail; + if (num > ULONG_MAX || (uid_t) num != num) { + rc = -ERANGE; + goto fail; + } + *uid = (uid_t) num; + + return 0; +fail: + DBG(UTILS, ul_debug("failed to convert '%s'= to number [rc=%d]", name, rc)); + return rc; +} + /** * mnt_match_options: * @optstr: options string
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor