* gnu/packages/patches/util-linux-CVE-2021-3995.patch, gnu/packages/patches/util-linux-CVE-2021-3996.patch: New files. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/linux.scm (util-linux)[replacement]: New field. (util-linux/fixed): New variable.
		
			
				
	
	
		
			146 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Fix CVE-2021-3995:
 | |
| 
 | |
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3995
 | |
| https://seclists.org/oss-sec/2022/q1/66
 | |
| 
 | |
| Patch copied from upstream source repository:
 | |
| 
 | |
| https://github.com/util-linux/util-linux/commit/f3db9bd609494099f0c1b95231c5dfe383346929
 | |
| 
 | |
| 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] 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(-)
 | |
| 
 | |
| diff --git a/include/strutils.h b/include/strutils.h
 | |
| index 6e95707ea..a84d29594 100644
 | |
| --- a/include/strutils.h
 | |
| +++ b/include/strutils.h
 | |
| @@ -106,8 +106,8 @@ static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nma
 | |
|  	if (n + 1 > nmax)
 | |
|  		n = nmax - 1;
 | |
|  
 | |
| +	memset(dest, '\0', nmax);
 | |
|  	memcpy(dest, src, n);
 | |
| -	dest[nmax-1] = '\0';
 | |
|  	return dest;
 | |
|  }
 | |
|  
 | |
| diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c
 | |
| index 173637a15..8773c65ff 100644
 | |
| --- a/libmount/src/context_umount.c
 | |
| +++ b/libmount/src/context_umount.c
 | |
| @@ -453,10 +453,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
 | |
|  	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;
 | |
|  
 | |
| @@ -473,11 +470,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
 | |
|  	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 */
 | |
| @@ -494,8 +487,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
 | |
|  		return 0;
 | |
|  	}
 | |
|  
 | |
| -	snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long) uid);
 | |
| -	return strncmp(user_id, uidstr, sz) == 0;
 | |
| +	return uid == entry_uid;
 | |
|  }
 | |
|  
 | |
|  /*
 | |
| diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
 | |
| index d43a83541..22442ec55 100644
 | |
| --- a/libmount/src/mountP.h
 | |
| +++ b/libmount/src/mountP.h
 | |
| @@ -399,6 +399,7 @@ extern const struct libmnt_optmap *mnt_optmap_get_entry(
 | |
|  			     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);
 | |
| diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c
 | |
| index 921b9318e..16800f571 100644
 | |
| --- a/libmount/src/optstr.c
 | |
| +++ b/libmount/src/optstr.c
 | |
| @@ -1076,6 +1076,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
 | |
| -- 
 | |
| 2.34.0
 | |
| 
 |