From 04894f015330e78ca5abca8c8cc2ee574fb115ba64733fe0af7c18cb15c2645a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Schr=C3=B6der?= Date: Fri, 15 Jun 2018 11:35:35 +0000 Subject: [PATCH] - really fix symlink attacks on rpm install [bnc#943457] OBS-URL: https://build.opensuse.org/package/show/Base:System/rpm?expand=0&rev=469 --- rpm.changes | 9 ++++++ rpm.spec | 4 ++- safesymlinks.diff | 44 +++++++++++++++++++++++++++++ verifynodup.diff | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 safesymlinks.diff create mode 100644 verifynodup.diff diff --git a/rpm.changes b/rpm.changes index b42e52c..22f5b6e 100644 --- a/rpm.changes +++ b/rpm.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri Jun 15 13:25:18 CEST 2018 - mls@suse.de + +- really fix symlink attacks on rpm install [bnc#943457] + [CVE-2017-7500] + new patch: safesymlinks.diff +- backport removal of user/group duplicate detection in verify + new patch: verifynodup.diff + ------------------------------------------------------------------- Mon Jun 11 11:43:36 CEST 2018 - mls@suse.de diff --git a/rpm.spec b/rpm.spec index 4198df3..6a4981a 100644 --- a/rpm.spec +++ b/rpm.spec @@ -132,6 +132,8 @@ Patch111: debugedit-bnc1076819.diff Patch112: hardlinks.diff Patch113: debugedit-riscv.patch Patch114: source_date_epoch_buildtime.diff +Patch115: safesymlinks.diff +Patch116: verifynodup.diff Patch6464: auto-config-update-aarch64-ppc64le.diff Patch6465: auto-config-update-riscv64.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -229,7 +231,7 @@ rm -f rpmdb/db.h %patch -P 85 %patch -P 93 -P 94 -P 99 %patch -P 100 -P 102 -P 103 -P 108 -%patch -P 109 -P 111 -P 112 -P 113 -P 114 +%patch -P 109 -P 111 -P 112 -P 113 -P 114 -P 115 -P 116 %ifarch aarch64 ppc64le riscv64 %patch6464 diff --git a/safesymlinks.diff b/safesymlinks.diff new file mode 100644 index 0000000..4d99f91 --- /dev/null +++ b/safesymlinks.diff @@ -0,0 +1,44 @@ +--- ./lib/fsm.c.orig 2018-06-15 11:15:50.320133057 +0000 ++++ ./lib/fsm.c 2018-06-15 11:15:56.240118124 +0000 +@@ -653,7 +653,7 @@ static int fsmUtime(const char *path, mo + return rc; + } + +-static int fsmVerify(const char *path, rpmfi fi, const struct stat *fsb) ++static int fsmVerify(const char *path, rpmfi fi) + { + int rc; + int saveerrno = errno; +@@ -684,7 +684,7 @@ static int fsmVerify(const char *path, r + if (rc) return rc; + errno = saveerrno; + /* Only permit directory symlinks by target owner and root */ +- if (S_ISDIR(dsb.st_mode) && (luid == 0 || luid == fsb->st_uid)) ++ if (S_ISDIR(dsb.st_mode) && (luid == 0 || luid == dsb.st_uid)) + return 0; + } + } else if (S_ISLNK(mode)) { +@@ -928,7 +928,7 @@ int rpmPackageFilesInstall(rpmts ts, rpm + } + /* Assume file does't exist when tmp suffix is in use */ + if (!suffix) { +- rc = fsmVerify(fpath, fi, &sb); ++ rc = fsmVerify(fpath, fi); + } else { + rc = (action == FA_TOUCH) ? 0 : RPMERR_ENOENT; + } +--- ./lib/verify.c.orig 2018-06-15 11:16:03.904098773 +0000 ++++ ./lib/verify.c 2018-06-15 11:23:42.842941766 +0000 +@@ -98,11 +98,8 @@ rpmVerifyAttrs rpmfilesVerify(rpmfiles f + struct stat dsb; + /* ...if it actually points to a directory */ + if (stat(fn, &dsb) == 0 && S_ISDIR(dsb.st_mode)) { +- uid_t fuid; + /* ...and is by a legit user, to match fsmVerify() behavior */ +- if (sb.st_uid == 0 || +- (rpmugUid(rpmfilesFUser(fi, ix), &fuid) == 0 && +- sb.st_uid == fuid)) { ++ if (sb.st_uid == 0 || sb.st_uid == dsb.st_uid) { + sb = dsb; /* struct assignment */ + } + } diff --git a/verifynodup.diff b/verifynodup.diff new file mode 100644 index 0000000..21e7617 --- /dev/null +++ b/verifynodup.diff @@ -0,0 +1,72 @@ +--- ./lib/verify.c.orig 2018-06-15 11:25:09.142724319 +0000 ++++ ./lib/verify.c 2018-06-15 11:27:32.246363744 +0000 +@@ -59,7 +59,7 @@ rpmVerifyAttrs rpmfilesVerify(rpmfiles f + rpmfileAttrs fileAttrs = rpmfilesFFlags(fi, ix); + rpmVerifyAttrs flags = rpmfilesVFlags(fi, ix); + const char * fn = rpmfilesFN(fi, ix); +- struct stat sb; ++ struct stat sb, fsb; + rpmVerifyAttrs vfy = RPMVERIFY_NONE; + + /* +@@ -88,7 +88,7 @@ rpmVerifyAttrs rpmfilesVerify(rpmfiles f + break; + } + +- if (fn == NULL || lstat(fn, &sb) != 0) { ++ if (fn == NULL || lstat(fn, &sb) != 0 || rpmfilesStat(fi, ix, 0, &fsb)) { + vfy |= RPMVERIFY_LSTATFAIL; + goto exit; + } +@@ -243,47 +243,11 @@ rpmVerifyAttrs rpmfilesVerify(rpmfiles f + vfy |= RPMVERIFY_MTIME; + } + +- if (flags & RPMVERIFY_USER) { +- const char * name = rpmugUname(sb.st_uid); +- const char * fuser = rpmfilesFUser(fi, ix); +- uid_t uid; +- int namematch = 0; +- int idmatch = 0; +- +- if (name && fuser) +- namematch = rstreq(name, fuser); +- if (fuser && rpmugUid(fuser, &uid) == 0) +- idmatch = (uid == sb.st_uid); +- +- if (namematch != idmatch) { +- rpmlog(RPMLOG_WARNING, +- _("Duplicate username or UID for user %s\n"), fuser); +- } +- +- if (!(namematch || idmatch)) +- vfy |= RPMVERIFY_USER; +- } +- +- if (flags & RPMVERIFY_GROUP) { +- const char * name = rpmugGname(sb.st_gid); +- const char * fgroup = rpmfilesFGroup(fi, ix); +- gid_t gid; +- int namematch = 0; +- int idmatch = 0; +- +- if (name && fgroup) +- namematch = rstreq(name, fgroup); +- if (fgroup && rpmugGid(fgroup, &gid) == 0) +- idmatch = (gid == sb.st_gid); +- +- if (namematch != idmatch) { +- rpmlog(RPMLOG_WARNING, +- _("Duplicate groupname or GID for group %s\n"), fgroup); +- } ++ if ((flags & RPMVERIFY_USER) && (sb.st_uid != fsb.st_uid)) ++ vfy |= RPMVERIFY_USER; + +- if (!(namematch || idmatch)) +- vfy |= RPMVERIFY_GROUP; +- } ++ if ((flags & RPMVERIFY_GROUP) && (sb.st_gid != fsb.st_gid)) ++ vfy |= RPMVERIFY_GROUP; + + exit: + return vfy;