Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package avahi for openSUSE:Factory checked in at 2026-07-20 09:57:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/avahi (Old) and /work/SRC/openSUSE:Factory/.avahi.new.24530 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "avahi" Mon Jul 20 09:57:18 2026 rev:179 rq:1366382 version:0.8 Changes: -------- --- /work/SRC/openSUSE:Factory/avahi/avahi.changes 2026-05-06 19:18:18.258091603 +0200 +++ /work/SRC/openSUSE:Factory/.avahi.new.24530/avahi.changes 2026-07-20 09:59:53.301237208 +0200 @@ -1,0 +2,6 @@ +Thu Jul 16 17:06:58 UTC 2026 - Michael Gorse <[email protected]> + +- Add avahi-CVE-2025-59529.patch: limit the number of simple + clients (bsc#1255451 CVE-2025-59529). + +------------------------------------------------------------------- New: ---- avahi-CVE-2025-59529.patch ----------(New B)---------- New: - Add avahi-CVE-2025-59529.patch: limit the number of simple clients (bsc#1255451 CVE-2025-59529). ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ avahi.spec ++++++ --- /var/tmp/diff_new_pack.Bhk03o/_old 2026-07-20 09:59:54.421274901 +0200 +++ /var/tmp/diff_new_pack.Bhk03o/_new 2026-07-20 09:59:54.421274901 +0200 @@ -150,6 +150,8 @@ Patch43: avahi-CVE-2026-34933.patch # PATCH-FIX-UPSTREAM avahi-CVE-2026-24401.patch bsc#1257235 [email protected] -- detect loop in CNAME record Patch44: avahi-CVE-2026-24401.patch +# PATCH-FIX-UPSTREAM avahi-CVE-2025-59529.patch bsc#1255451 [email protected] -- limit the number of simple clients. +Patch45: avahi-CVE-2025-59529.patch BuildRequires: fdupes BuildRequires: gcc-c++ BuildRequires: gdbm-devel ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.Bhk03o/_old 2026-07-20 09:59:54.497277459 +0200 +++ /var/tmp/diff_new_pack.Bhk03o/_new 2026-07-20 09:59:54.505277728 +0200 @@ -1,6 +1,6 @@ -mtime: 1777971831 -commit: 1ad7fff576de05e40163ce8eea6df97b3941be8e949c925ce93c16ec8c17d364 +mtime: 1784234774 +commit: 996edd5a3dc58c88a1f7d18b0989acd3fffc4bc7142d34290ab2b2d70cfaca11 url: https://src.opensuse.org/GNOME/avahi -revision: 1ad7fff576de05e40163ce8eea6df97b3941be8e949c925ce93c16ec8c17d364 +revision: 996edd5a3dc58c88a1f7d18b0989acd3fffc4bc7142d34290ab2b2d70cfaca11 projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj ++++++ avahi-CVE-2025-59529.patch ++++++ Backport of https://github.com/avahi/avahi/pull/808.patch diff -urp avahi-0.8.orig/avahi-daemon/main.c avahi-0.8/avahi-daemon/main.c --- avahi-0.8.orig/avahi-daemon/main.c 2020-02-16 21:41:02.384380713 -0600 +++ avahi-0.8/avahi-daemon/main.c 2026-07-16 11:08:34.718593886 -0500 @@ -87,6 +87,9 @@ #include "dbus-protocol.h" #endif +/* Maximal number of concurrent simple protocol clients. */ +#define MAX_NOFILE_LIMIT 4096 + AvahiServer *avahi_server = NULL; AvahiSimplePoll *simple_poll_api = NULL; static char *argv0 = NULL; @@ -1140,6 +1143,7 @@ static int run_server(DaemonConfig *c) { const AvahiPoll *poll_api = NULL; AvahiWatch *sig_watch = NULL; int retval_is_sent = 0; + unsigned nofiles; #ifdef HAVE_INOTIFY AvahiWatch *inotify_watch = NULL; #endif @@ -1172,7 +1176,12 @@ static int run_server(DaemonConfig *c) { goto finish; } - if (simple_protocol_setup(poll_api) < 0) + /* We accept clients only of 3/4 file descriptors allowed + * in this process. Keep extra for UDP sockets. */ + nofiles = config.rlimit_nofile * 3/4; + if (nofiles > MAX_NOFILE_LIMIT) + nofiles = MAX_NOFILE_LIMIT; + if (simple_protocol_setup(poll_api, nofiles) < 0) goto finish; #ifdef HAVE_DBUS @@ -1451,6 +1460,20 @@ fail: return r; } +static int get_one_rlimit(int resource, rlim_t *limit, const char *name) { + struct rlimit rl = {0,}; + int r; + + r = getrlimit(resource, &rl); + if (r < 0) { + avahi_log_warn("getrlimit(%s) failed: %s", name, strerror(errno)); + } else { + *limit = rl.rlim_cur; + } + + return r; +} + static void set_one_rlimit(int resource, rlim_t limit, const char *name) { struct rlimit rl; rl.rlim_cur = rl.rlim_max = limit; @@ -1506,6 +1529,11 @@ static void init_rand_seed(void) { srand(seed); } +static void read_rlimits(void) { + config.rlimit_nofile_set = 0; + (void)get_one_rlimit(RLIMIT_NOFILE, &config.rlimit_nofile, "RLIMIT_NOFILE"); +} + int main(int argc, char *argv[]) { int r = 255; int wrote_pid_file = 0; @@ -1604,6 +1632,7 @@ int main(int argc, char *argv[]) { goto finish; } + read_rlimits(); if (load_config_file(&config) < 0) goto finish; Only in avahi-0.8/avahi-daemon: main.c.orig diff -urp avahi-0.8.orig/avahi-daemon/simple-protocol.c avahi-0.8/avahi-daemon/simple-protocol.c --- avahi-0.8.orig/avahi-daemon/simple-protocol.c 2026-07-16 11:08:17.674376312 -0500 +++ avahi-0.8/avahi-daemon/simple-protocol.c 2026-07-16 11:08:34.718168048 -0500 @@ -47,6 +47,9 @@ #ifdef ENABLE_CHROOT #include "chroot.h" #endif +#ifdef HAVE_STRUCT_XUCRED +#include <sys/ucred.h> +#endif #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX @@ -57,7 +60,87 @@ #define BUFFER_SIZE (20*1024) -#define CLIENTS_MAX 50 +#if __linux__ +/* Linux specific support, man 7 unix */ +typedef struct ucred AvahiCred; + + +static uid_t credentials_getuid(const AvahiCred *cred) { + return cred->uid; +} + +static gid_t credentials_getgid(const AvahiCred *cred) { + return cred->gid; +} + +static pid_t credentials_getpid(const AvahiCred *cred) { + return cred->pid; +} + +static int credentials_getsockopt(int fd, AvahiCred *cred, socklen_t *len) { + *len = sizeof(*cred); + memset(cred, 0, sizeof(*cred)); + return getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, len); +} + +# define CRED_FMT "uid=%lu gid=%lu pid=%lu" +# define CRED_VALS(ucred) (long)credentials_getuid(ucred), (long)credentials_getgid(ucred), (long)credentials_getpid(ucred) + +#elif defined(HAVE_STRUCT_XUCRED) && defined(XUCRED_VERSION) +/* FreeBSD support, man 4 unix */ +typedef struct xucred AvahiCred; + +static int credentials_version_check(const AvahiCred *cred) { + if (cred->cr_version != XUCRED_VERSION) { + avahi_log_debug("credentials_version_check: unsupported version %d", + cred->cr_version); + return 0; + } + return 1; +} + +static uid_t credentials_getuid(const AvahiCred *cred) { + if (!credentials_version_check(cred)) + return 0; + return cred->cr_uid; +} + +static gid_t credentials_getgid(const AvahiCred *cred) { + if (!credentials_version_check(cred) || cred->cr_ngroups <= 0) + return 0; + return cred->cr_groups[0]; +} + +static pid_t credentials_getpid(const AvahiCred *cred) { + if (!credentials_version_check(cred)) + return 0; + return cred->cr_pid; +} + +static int credentials_getsockopt(int fd, AvahiCred *cred, socklen_t *len) { + *len = sizeof(*cred); + memset(cred, 0, sizeof(*cred)); + return getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, cred, len); +} + +# define CRED_FMT "uid=%lu gid=%lu pid=%lu" +# define CRED_VALS(ucred) (long)credentials_getuid(ucred), (long)credentials_getgid(ucred), (long)credentials_getpid(ucred) + +#else +/* No support */ +# define CRED_FMT "%s" +# define CRED_VALS(ucred) ucred +typedef unsigned char AvahiCred; /* need known type size. */ + +static uid_t credentials_getuid(const AvahiCred *cred) { + (void)cred; return 0; /* no support for getting remote user. */ +} + +static int credentials_getsockopt(int fd, AvahiCred *cred, socklen_t *len) { + (void)fd; *len = sizeof(*cred); *cred = 0; + return 0; +} +#endif typedef struct Client Client; typedef struct Server Server; @@ -77,6 +160,7 @@ struct Client { int fd; AvahiWatch *watch; + AvahiCred credentials; char inbuf[BUFFER_SIZE], outbuf[BUFFER_SIZE]; size_t inbuf_length, outbuf_length; @@ -97,6 +181,8 @@ struct Server { AVAHI_LLIST_HEAD(Client, clients); unsigned n_clients; + unsigned max_clients; /*< Maximal number of all simple clients. */ + unsigned max_uid_clients; /*< Maximal number of clients of one UID. */ int remove_socket; }; @@ -121,12 +207,14 @@ static void client_free(Client *c) { c->server->poll_api->watch_free(c->watch); close(c->fd); + avahi_log_debug("simple client %d finished: " CRED_FMT, + c->fd, CRED_VALS(&c->credentials)); AVAHI_LLIST_REMOVE(Client, clients, c->server->clients, c); avahi_free(c); } -static void client_new(Server *s, int fd) { +static void client_new(Server *s, int fd, const AvahiCred *cred) { Client *c; assert(fd >= 0); @@ -135,6 +223,7 @@ static void client_new(Server *s, int fd c->server = s; c->fd = fd; c->state = CLIENT_IDLE; + c->credentials = *cred; c->inbuf_length = c->outbuf_length = 0; @@ -263,6 +352,15 @@ static void dns_server_browser_callback( } } +static void log_request(const Client *c, const char *cmd, const char *arg) { + if (arg != NULL) + avahi_log_debug(__FILE__": Got %s request for '%s'. " CRED_FMT, + cmd, arg, CRED_VALS(&c->credentials)); + else + avahi_log_debug(__FILE__": Got %s request. " CRED_FMT, + cmd, CRED_VALS(&c->credentials)); +} + static void handle_line(Client *c, const char *s) { char cmd[64], arg[64]; int n_args; @@ -298,19 +396,19 @@ static void handle_line(Client *c, const if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_INET, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; - avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); + log_request(c, cmd, arg); } else if (strcmp(cmd, "RESOLVE-HOSTNAME-IPV6") == 0 && n_args == 2) { c->state = CLIENT_RESOLVE_HOSTNAME; if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_INET6, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; - avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); + log_request(c, cmd, arg); } else if (strcmp(cmd, "RESOLVE-HOSTNAME") == 0 && n_args == 2) { c->state = CLIENT_RESOLVE_HOSTNAME; if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; - avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); + log_request(c, cmd, arg); } else if (strcmp(cmd, "RESOLVE-ADDRESS") == 0 && n_args == 2) { AvahiAddress addr; @@ -323,32 +421,28 @@ static void handle_line(Client *c, const goto fail; } - avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); - + log_request(c, cmd, arg); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS-IPV4") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_INET, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; - client_output_printf(c, "+ Browsing ...\n"); - - avahi_log_debug(__FILE__": Got %s request.", cmd); + client_output_printf(c, "+ Browsing ...\n"); + log_request(c, cmd, NULL); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS-IPV6") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_INET6, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; - client_output_printf(c, "+ Browsing ...\n"); - - avahi_log_debug(__FILE__": Got %s request.", cmd); + client_output_printf(c, "+ Browsing ...\n"); + log_request(c, cmd, NULL); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; - client_output_printf(c, "+ Browsing ...\n"); - - avahi_log_debug(__FILE__": Got %s request.", cmd); + client_output_printf(c, "+ Browsing ...\n"); + log_request(c, cmd, NULL); } else { client_output_printf(c, "%+i Invalid command \"%s\", try \"HELP\".\n", AVAHI_ERR_INVALID_OPERATION, cmd); c->state = CLIENT_DEAD; @@ -435,6 +529,48 @@ static void client_work(AvahiWatch *watc (c->inbuf_length < sizeof(c->inbuf) ? AVAHI_WATCH_IN : 0)); } +static int is_client_allowed(Server *s, int cfd, AvahiCred *cred) { + socklen_t len = sizeof(*cred); + unsigned n_clients; + uid_t uid; + + assert(s != NULL); + + n_clients = s->n_clients + 1; + if (credentials_getsockopt(cfd, cred, &len) != 0) { + avahi_log_error("credentials_getsockopt(%d): %s", cfd, strerror(errno)); + return 0; + } + + if (n_clients > s->max_clients) { + avahi_log_debug("simple client %d refused: "CRED_FMT" too many clients", + cfd, CRED_VALS(cred)); + return 0; + } + + uid = credentials_getuid(cred); + if (uid != 0 && n_clients > s->max_uid_clients) { + // There is enough clients to reach limit for one UID. + // Check this UID does not have too many requests already. + Client *c; + unsigned present = 0; + + for (c = s->clients; c; c = c->clients_next) { + if (credentials_getuid(&c->credentials) == uid) { + present++; + if (present > s->max_uid_clients) { + avahi_log_debug("simple client %d refused: "CRED_FMT" too many uid clients: %u", + cfd, CRED_VALS(cred), present); + return 0; + } + } + } + } + avahi_log_debug("simple client %d/%u accepted: "CRED_FMT, + cfd, n_clients, CRED_VALS(cred)); + return 1; +} + static void server_work(AVAHI_GCC_UNUSED AvahiWatch *watch, int fd, AvahiWatchEvent events, void *userdata) { Server *s = userdata; @@ -443,14 +579,23 @@ static void server_work(AVAHI_GCC_UNUSED if (events & AVAHI_WATCH_IN) { int cfd; - if ((cfd = accept(fd, NULL, NULL)) < 0) - avahi_log_error("accept(): %s", strerror(errno)); - else - client_new(s, cfd); + if ((cfd = accept(fd, NULL, NULL)) < 0) { + if (errno != EMFILE && errno != ENFILE) + avahi_log_error(__FILE__" accept(): %s", strerror(errno)); + else // Avoid client ability to flood log with too many requests + avahi_log_debug(__FILE__" accept(): %s", strerror(errno)); + } else { + AvahiCred cred; + if (is_client_allowed(s, cfd, &cred)) + client_new(s, cfd, &cred); + else { + close(cfd); + } + } } } -int simple_protocol_setup(const AvahiPoll *poll_api) { +int simple_protocol_setup(const AvahiPoll *poll_api, unsigned max_clients) { struct sockaddr_un sa; mode_t u; int n; @@ -462,6 +607,8 @@ int simple_protocol_setup(const AvahiPol server->remove_socket = 0; server->fd = -1; server->n_clients = 0; + server->max_clients = max_clients; + server->max_uid_clients = max_clients / 2; AVAHI_LLIST_HEAD_INIT(Client, server->clients); server->watch = NULL; @@ -521,6 +668,8 @@ int simple_protocol_setup(const AvahiPol umask(u); server->watch = poll_api->watch_new(poll_api, server->fd, AVAHI_WATCH_IN, server_work, server); + avahi_log_info("Maximal simple clients: %u, per_uid: %u", + max_clients, server->max_uid_clients); return 0; Only in avahi-0.8/avahi-daemon: simple-protocol.c.orig Only in avahi-0.8/avahi-daemon: .simple-protocol.c.swp diff -urp avahi-0.8.orig/avahi-daemon/simple-protocol.h avahi-0.8/avahi-daemon/simple-protocol.h --- avahi-0.8.orig/avahi-daemon/simple-protocol.h 2015-03-31 23:58:14.153727024 -0500 +++ avahi-0.8/avahi-daemon/simple-protocol.h 2026-07-16 11:08:34.717204350 -0500 @@ -22,7 +22,10 @@ #include <avahi-common/watch.h> -int simple_protocol_setup(const AvahiPoll *poll_api); +/* max_clients is number of concurrent simple mdns clients allowed. + * When limit is reached, new clients are immediately closed. + * Per UID limit is derived from this number. */ +int simple_protocol_setup(const AvahiPoll *poll_api, unsigned max_clients); void simple_protocol_shutdown(void); void simple_protocol_restart_queries(void); diff -urp avahi-0.8.orig/configure.ac avahi-0.8/configure.ac --- avahi-0.8.orig/configure.ac 2020-02-18 01:01:15.816990957 -0600 +++ avahi-0.8/configure.ac 2026-07-16 11:08:34.718395860 -0500 @@ -223,6 +223,21 @@ if test $avahi_cv_has_struct_lifconf = y fi # +# Check for xucred struct; only present on FreeBSD +# +AC_MSG_CHECKING(for struct xucred) +AC_CACHE_VAL(avahi_cv_has_struct_xucred, +[AC_TRY_COMPILE( +[#include <sys/socket.h> +#include <sys/ucred.h> +],[sizeof (struct xucred);], +avahi_cv_has_struct_xucred=yes,avahi_cv_has_struct_xucred=no)]) +AC_MSG_RESULT($avahi_cv_has_struct_xucred) +if test $avahi_cv_has_struct_xucred = yes; then + AC_DEFINE(HAVE_STRUCT_XUCRED,1,[Define if there is a struct xucred.]) +fi + +# # Check for struct ip_mreqn # AC_MSG_CHECKING(for struct ip_mreqn) Only in avahi-0.8: configure.ac.orig ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-07-16 22:46:14.000000000 +0200 @@ -0,0 +1,4 @@ +*.obscpio +*.osc +_build.* +.pbuild
