Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package arpwatch for openSUSE:Factory checked in at 2021-07-01 07:05:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/arpwatch (Old) and /work/SRC/openSUSE:Factory/.arpwatch.new.2625 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "arpwatch" Thu Jul 1 07:05:38 2021 rev:34 rq:903193 version:2.1a15 Changes: -------- --- /work/SRC/openSUSE:Factory/arpwatch/arpwatch.changes 2021-02-09 21:17:20.942848142 +0100 +++ /work/SRC/openSUSE:Factory/.arpwatch.new.2625/arpwatch.changes 2021-07-01 07:05:50.555379526 +0200 @@ -1,0 +2,7 @@ +Tue Jun 29 07:10:40 UTC 2021 - Johannes Segitz <jsegitz@suse.com> + +- Fixed local privilege escalation from runtime user to root + (bsc#1186240, CVE-2021-25321) +- Added service_* calls for the @.service file + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ arpwatch.spec ++++++ --- /var/tmp/diff_new_pack.fkSmAl/_old 2021-07-01 07:05:51.091375339 +0200 +++ /var/tmp/diff_new_pack.fkSmAl/_new 2021-07-01 07:05:51.095375308 +0200 @@ -103,17 +103,21 @@ %pre %service_add_pre arpwatch.service +%service_add_pre arpwatch@.service %preun %service_del_preun arpwatch.service +%service_del_preun arpwatch@.service %post %fillup_only %tmpfiles_create %{_tmpfilesdir}/arpwatch.conf %service_add_post arpwatch.service +%service_add_post arpwatch@.service %postun %service_del_postun arpwatch.service +%service_del_postun arpwatch@.service %files %{_unitdir}/arpwatch.service ++++++ arpwatch-2.1a11-drop-privs.dif ++++++ --- /var/tmp/diff_new_pack.fkSmAl/_old 2021-07-01 07:05:51.135374995 +0200 +++ /var/tmp/diff_new_pack.fkSmAl/_new 2021-07-01 07:05:51.135374995 +0200 @@ -1,5 +1,7 @@ ---- a/arpwatch.c -+++ b/arpwatch.c +Index: arpwatch-2.1a15/arpwatch.c +=================================================================== +--- arpwatch-2.1a15.orig/arpwatch.c ++++ arpwatch-2.1a15/arpwatch.c @@ -64,6 +64,8 @@ struct rtentry; #include <string.h> #include <syslog.h> @@ -9,7 +11,7 @@ #include <pcap.h> -@@ -152,6 +154,52 @@ int sanity_toring(struct toring_header * +@@ -152,6 +154,66 @@ int sanity_toring(struct toring_header * #endif __dead void usage(void) __attribute__((volatile)); @@ -34,14 +36,28 @@ + } + lastslash[0]='\0'; + ++ if (!safe_base_path(arpfiledir)) { ++ syslog(LOG_ERR, "Fatal: directory structure %s not safe, can't operate here. Please make root owner of underlying directories and remove write access for other", arpfiledir); ++ exit(1); ++ } + ++ // ensure we have a safe place to operate ++ if (lchown( arpfiledir, 0, 0) != 0 ) { ++ syslog(LOG_ERR, "Fatal: could not chown %s to root).", arpfiledir); ++ exit(1); ++ } ++ // change permissions of the file if it exists ++ if (!access(arpfile, F_OK) && lchown ( arpfile, pw->pw_uid, -1) != 0) { ++ syslog(LOG_ERR, "Fatal: could not chown %s to %d).", arpfile, pw->pw_uid); ++ exit(1); ++ } + /* files arp.dat.eth0- and arp.dat.eth0.new that are created + as backup/lastversion and for temporary storage are -+ deleted before created again. */ -+ if ( chown ( arpfile, pw->pw_uid, pw->pw_gid) != 0 || -+ chown ( arpfiledir, pw->pw_uid, pw->pw_gid) != 0 ) { -+ syslog(LOG_ERR, "Fatal: could not chown %s and %s to %d,%d).", -+ arpfiledir,arpfile, pw->pw_uid, pw->pw_gid); ++ deleted before created again, therefor the users needs ++ to control this directory . */ ++ if ( lchown ( arpfiledir, pw->pw_uid, -1) != 0 ) { ++ syslog(LOG_ERR, "Fatal: could not chown %s to %d).", ++ arpfiledir, pw->pw_uid); + exit(1); + } + free(arpfiledir); @@ -62,7 +78,7 @@ int main(int argc, char **argv) { -@@ -164,6 +212,7 @@ main(int argc, char **argv) +@@ -164,6 +226,7 @@ main(int argc, char **argv) register char *interface, *rfilename; struct bpf_program code; char errbuf[PCAP_ERRBUF_SIZE]; @@ -70,7 +86,7 @@ if (argv[0] == NULL) prog = "arpwatch"; -@@ -181,7 +230,7 @@ main(int argc, char **argv) +@@ -181,7 +244,7 @@ main(int argc, char **argv) interface = NULL; rfilename = NULL; pd = NULL; @@ -79,7 +95,7 @@ switch (op) { case 'd': -@@ -213,6 +262,16 @@ main(int argc, char **argv) +@@ -213,6 +276,16 @@ main(int argc, char **argv) rfilename = optarg; break; @@ -96,7 +112,7 @@ default: usage(); } -@@ -295,8 +354,11 @@ main(int argc, char **argv) +@@ -295,8 +368,11 @@ main(int argc, char **argv) * Revert to non-privileged user after opening sockets * (not needed on most systems). */ @@ -110,7 +126,7 @@ /* Must be ethernet or fddi or tokenring */ linktype = pcap_datalink(pd); -@@ -842,6 +904,6 @@ usage(void) +@@ -842,6 +918,6 @@ usage(void) (void)fprintf(stderr, "Version %s\n", version); (void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]" @@ -118,3 +134,75 @@ + " [-n net[/width]] [-r file] [-u username]\n", prog); exit(1); } +Index: arpwatch-2.1a15/util.c +=================================================================== +--- arpwatch-2.1a15.orig/util.c ++++ arpwatch-2.1a15/util.c +@@ -29,6 +29,7 @@ static const char rcsid[] = + + #include <sys/types.h> + #include <sys/file.h> ++#include <sys/stat.h> + + #include <fcntl.h> + #ifdef HAVE_MEMORY_H +@@ -186,3 +187,47 @@ savestr(register const char *str) + strsize -= i; + return (cp); + } ++ ++int safe_base_path(char *arpfiledir) { ++ // check directories below arpfiledir for safe ownwership/permissions ++ char *path_component; ++ char *lastslash = NULL; ++ int safe_path = 1; ++ ++ if (!arpfiledir) { ++ syslog(LOG_ERR, "Fatal: safe_base_path invalid invocation."); ++ exit(1); ++ } ++ ++ path_component = malloc(strlen(arpfiledir)+1); ++ if(path_component == NULL) { ++ syslog(LOG_ERR, "Fatal: malloc()."); ++ exit(1); ++ } ++ strcpy(path_component, arpfiledir); ++ ++ while ((lastslash = strrchr(path_component, '/'))) { ++ struct stat stats; ++ ++ lastslash[0]='\0'; ++ if ( lstat(path_component, &stats) ) { ++ /* on the last iteration the string will be empty and this fails, ++ which is okay, if / is unsafe all is lost anyway and we can ++ skip the check. Otherwise fail safe if lstat doesn't work */ ++ if (strlen(path_component)) ++ safe_path = 0; ++ } else { ++ if ( stats.st_uid != 0 || ++ stats.st_gid != 0 || ++ stats.st_mode & S_IWOTH ++ ) { ++ /* this is not a safe path to operate on with privileges because ++ it isn't owned by root:root or others can write there */ ++ safe_path = 0; ++ } ++ } ++ } ++ ++ free(path_component); ++ return safe_path; ++} +Index: arpwatch-2.1a15/util.h +=================================================================== +--- arpwatch-2.1a15.orig/util.h ++++ arpwatch-2.1a15/util.h +@@ -5,6 +5,7 @@ int dump(void); + void dumpone(u_int32_t, u_char *, time_t, char *); + int readdata(void); + char *savestr(const char *); ++int safe_base_path(char *); + + extern char *arpdir; + extern char *newarpfile;