Compare commits

...
35 Commits
31 ... 47
Author SHA1 Message Date
Patrick McCarty 6653992aba Release v47
Fixes a bug with clr_debug_prepare's handling of broken symlinks.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-12-10 17:10:44 -08:00
Patrick McCarty 0af0308dd2 Revert "have tar follow symlinks"
After closer inspection, I've determined that prior to this commit,
clr_debug_prepare was behaving properly with respect to the handling of
symlinks in debuginfo packages. Reverting this commit fixes the issue.

Details:

 - Symlinks under /usr/lib/debug/.build-id that are not broken should be
 unsymlinked so that the actual debuginfo is added to the automatic
 debuginfo tarballs. In the debuginfo packages, these files have a
 .debug extension and point to files under /usr/lib/debug/usr.

 - Symlinks under /usr/lib/debug/.build-id that *are* broken cannot be
 unsymlinked, and therefore, tar should not follow these symlinks,
 because fatal errors (and empty tarballs) are the result. These
 symlinks lack the .debug extension and point to the corresponding
 libraries or binaries under /usr when exposed via clr_debug_fuse. So it
 is correct for the symlinks to be broken when packaged by
 clr_debug_prepare, since they point to non-debuginfo files, and the
 debuginfo.raw directory tree only contains debuginfo content.

This reverts commit 7dcddfd0ca8f5539ef34028a1c680f6e82dcf246.
2018-12-10 17:04:05 -08:00
Patrick McCarty 8ace503438 Release v46
This release fixes a build issue when not passing -Wl,--copy-dt-needed-entries
to the compiler.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-05-25 21:56:43 -07:00
Patrick McCarty 2c87f83adc build: add LIBSYSTEMD_LIBS to link line
For the regular Clear Linux build, the -lsystemd option was not needed at link
time due to -Wl,--copy-dt-needed-entries being used. Without that option
though, the linking of clr_debug_daemon will fail.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-05-25 21:55:28 -07:00
Patrick McCarty 67b9b3acc8 Update gitignore
Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-05-25 21:38:06 -07:00
Arjan van de Ven d108c0af64 add cdn-alt 2018-05-17 13:54:16 +00:00
Auke Kok 98e802b4cc Also install socket unit. 2018-04-24 13:04:33 -07:00
Auke Kok 612801b0c8 Make -daemon socket activated. 2018-04-23 15:15:33 -07:00
Arjan van de Ven 3c2ad26baa have tar follow symlinks 2017-12-23 00:49:24 +00:00
Arjan van de Ven d20d585e5c much shorter timeouts 2017-12-10 14:25:07 +00:00
Icarus Sparry 1f3a0f0be4 Extract tar file as dbginfo
Make /var/cache/debuginfo and its contents owned by dgbinfo. Create
the directories as this user, and switch to run as this user.

Signed-off-by: Icarus Sparry <icarus.w.sparry@intel.com>
2017-10-31 13:35:29 -07:00
Icarus Sparry d2d67bdb1d Change tmpfiles.d configuration
Use the dbginfo user for the directories.

Signed-off-by: Icarus Sparry <icarus.w.sparry@intel.com>
2017-10-31 09:47:39 -07:00
Auke Kok 60db7bab0f v43 2017-06-06 13:28:11 -07:00
Auke Kok ef6b11498a DefaultDependencies keyword is only valid in [Unit] context. 2017-06-06 13:27:20 -07:00
Auke Kok efeed3e83f v42. 2017-06-01 16:22:00 -07:00
Auke Kok f5542e7fbb Fetch timestamp from debuginfo server.
We trigger redownloads from the server if the timestamp of
downloaded tar files is too new. An easy way around this issue
is to request the timestamp from the server instead of using
the download time. A `touch` of the tar then assures that
the downloaded file has the same timestamp as the server has.
2017-06-01 16:19:15 -07:00
Arjan van de Ven be8a99da53 allow service to start early 2017-05-07 15:42:30 +00:00
Ikey Doherty c9304402e2 Bump v38 to resync configure + tags
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2017-03-09 17:48:59 +00:00
Ikey Doherty 6e202f13f7 Bump v34
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2017-03-09 17:46:10 +00:00
Ikey Doherty 6735f8f6ed nica/files: Ensure we really do break on a read error
Previously nc_copy_file would return true regardless of a source read
error, flagged in analysis. Ensure we bypass the set of ret to true and
return the correct value in all instances.

Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2017-03-09 15:44:09 +00:00
Ikey Doherty 8b3777ab99 server: Remove useless assignment of prefix
This particular assignment is never used, as if this path fails, we go to
the thread end. We then reassign prefix after we split the input string.

Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2017-03-09 15:38:29 +00:00
Ikey Doherty 84350939ef nica/hashmap: Fix signature issue & item dereference
The signature was incorrect for inserting buckets, as we used an int, not
a boolean. Another issue resolved with this change is the potential
dereferencing of a null pointer by not having checked first if item was
NULL when setting the next pointer.

Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2017-03-09 15:35:29 +00:00
Arjan van de Ven 72b1120a40 add --no-same-permissions as well 2017-03-09 14:52:37 +00:00
Auke Kok d3d5fab301 Tag v33 2016-11-01 09:20:19 -07:00
Auke Kok e377433a9d Return on error here too.
Missed a 'return' catching an error.
2016-11-01 09:15:12 -07:00
Auke Kok afa92c77b1 Add reasonable connection timeout limits.
Adds a 30second connection timeout, and a low bandwith timeout
value (at 1kb/sec over 30 seconds) where the attempt will fail.
This provides some feedback to users that network issues are
preventing debug info from being loaded.
2016-11-01 09:15:12 -07:00
Arjan van de Ven a01ce4c329 dumb down due to limited infra 2016-11-01 13:17:49 +00:00
Arjan van de Ven 1eaaac582c use http/2 2016-11-01 12:56:35 +00:00
Arjan van de Ven 935dbee3c7 use CDN urls 2016-11-01 12:53:04 +00:00
Arjan van de Ven 0065ef2670 don't spew the journal 2016-11-01 12:52:17 +00:00
Ikey Doherty b5b4030f7c Release v32
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2016-05-18 19:21:20 +01:00
Ikey Doherty de9e0ce5c5 server: Disallow gdb -p attach, drop CAP_SYS_ADMIN
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2016-05-18 15:03:28 +01:00
Ikey Doherty 9e400bd149 Use correct types in absence of stdatomic.h
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2016-05-18 14:37:07 +01:00
Ikey Doherty f5a65358af Use pthread mutex in the absence of stdatomic C11 atomics
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2016-05-18 14:33:26 +01:00
Ikey Doherty c82a007960 Add configure output, and check for stdatomics
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
2016-05-18 14:18:56 +01:00
11 changed files with 228 additions and 43 deletions
+1
View File
@@ -8,6 +8,7 @@ clr_debug_prepare
Makefile Makefile
Makefile.in Makefile.in
aclocal.m4 aclocal.m4
ar-lib
autom4te.cache/ autom4te.cache/
compile compile
config.h config.h
+5 -4
View File
@@ -1,4 +1,4 @@
EXTRA_DIST = COPYING clr_debug_fuse.service clr_debug_daemon.service debuginfo.conf EXTRA_DIST = COPYING clr_debug_fuse.service clr_debug_daemon.service clr_debug_daemon.socket debuginfo.conf
DISTCHECK_CONFIGURE_FLAGS = \ DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) \
@@ -33,15 +33,16 @@ clr_debug_fuse_SOURCES = src/fuse.c src/client.c
clr_debug_daemon_SOURCES = src/server.c clr_debug_daemon_SOURCES = src/server.c
clr_debug_daemon_CFLAGS = \ clr_debug_daemon_CFLAGS = \
-pthread \ -pthread \
$(AM_CFLAGS) $(AM_CFLAGS) \
$(LIBSYSTEMD_CFLAGS)
clr_debug_prepare_SOURCES = src/prepare.c clr_debug_prepare_SOURCES = src/prepare.c
clr_debug_fuse_LDADD = ${fuse_LIBS} libnica.la clr_debug_fuse_LDADD = ${fuse_LIBS} libnica.la
clr_debug_daemon_LDADD = ${curl_LIBS} libnica.la clr_debug_daemon_LDADD = ${curl_LIBS} libnica.la ${LIBSYSTEMD_LIBS}
clr_debug_prepare_LDADD = libnica.la clr_debug_prepare_LDADD = libnica.la
systemdsystemunit_DATA = clr_debug_fuse.service clr_debug_daemon.service systemdsystemunit_DATA = clr_debug_fuse.service clr_debug_daemon.service clr_debug_daemon.socket
tmpfiles_DATA = debuginfo.conf tmpfiles_DATA = debuginfo.conf
+1
View File
@@ -1,5 +1,6 @@
[Unit] [Unit]
Description=Clear Linux debuginfo daemon Description=Clear Linux debuginfo daemon
DefaultDependencies=no
[Service] [Service]
Type=simple Type=simple
+9
View File
@@ -0,0 +1,9 @@
[Unit]
Description=Clear Linux OS debuginfo daemon
[Socket]
ListenStream=/run/clr-debug-info
SocketMode=0600
[Install]
WantedBy=sockets.target
+1
View File
@@ -1,6 +1,7 @@
[Unit] [Unit]
Description=Clear Linux debuginfo fuse monitor Description=Clear Linux debuginfo fuse monitor
After=clr_debug_daemon.service After=clr_debug_daemon.service
DefaultDependencies=no
[Service] [Service]
Type=simple Type=simple
+30 -1
View File
@@ -2,15 +2,17 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.66]) AC_PREREQ([2.66])
AC_INIT(clr-debug-info, 31, arjan@linux.intel.com) AC_INIT(clr-debug-info, 47, arjan@linux.intel.com)
AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects]) AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
AC_PROG_CC AC_PROG_CC
AM_PROG_AR
AC_LANG(C) AC_LANG(C)
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
PKG_CHECK_MODULES([curl], [libcurl]) PKG_CHECK_MODULES([curl], [libcurl])
PKG_CHECK_MODULES([fuse], [fuse]) PKG_CHECK_MODULES([fuse], [fuse])
PKG_CHECK_MODULES([SYSTEMD], [systemd]) PKG_CHECK_MODULES([SYSTEMD], [systemd])
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd])
LT_INIT LT_INIT
dir="" dir=""
@@ -27,5 +29,32 @@ AC_ARG_WITH([systemdtmpfilesdir], AS_HELP_STRING([--with-systemdtmpfilesdir=DIR]
test -z "${dir}" && dir=/usr/lib/tmpfiles.d test -z "${dir}" && dir=/usr/lib/tmpfiles.d
AC_SUBST(tmpfilesdir, [${dir}]) AC_SUBST(tmpfilesdir, [${dir}])
AC_CHECK_HEADER([stdatomic.h], [have_atomics="yes"], [have_atomics="no"])
if test x$have_atomics = "xyes"; then
AC_DEFINE([HAVE_ATOMIC_SUPPORT], [1], [stdatomic supported by compiler])
else
AC_MSG_WARN([C11 stdatomic support unavailable. Falling back to slow mutex])
fi
AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([Makefile])
AC_OUTPUT AC_OUTPUT
AC_MSG_RESULT([
clr-debuginfo $VERSION
prefix: ${prefix}
libdir: ${libdir}
sysconfdir: ${sysconfdir}
exec_prefix: ${exec_prefix}
bindir: ${bindir}
datarootdir: ${datarootdir}
compiler: ${CC}
cflags: ${CFLAGS}
ldflags: ${LDFLAGS}
systemd-unit-dir: ${systemdsystemunitdir}
tmpfiles.d: ${tmpfilesdir}
C11 stdatomic support: ${have_atomics}
])
+4 -2
View File
@@ -8,5 +8,7 @@
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details
# Clear tmp directories separately, to make them easier to override # Clear tmp directories separately, to make them easier to override
d /var/cache/debuginfo/lib 755 root root 10d # Unfortunatly tmpfiles doesn't change the ownership for things if they
d /var/cache/debuginfo/src 755 root root 1d # are not listed.
d /var/cache/debuginfo/lib 755 dbginfo dbginfo 10d
d /var/cache/debuginfo/src 755 dbginfo dbginfo 1d
+5 -5
View File
@@ -37,8 +37,8 @@
#include <unistd.h> #include <unistd.h>
/* 0.75 seconds timeout */ /* 0.75 seconds timeout */
#define TIMEOUT 750000 #define TIMEOUT 75000
#define TIMEOUT2 15000 #define TIMEOUT2 1500
#define TIMEOUT3 500 #define TIMEOUT3 500
char *prefix = "src"; char *prefix = "src";
@@ -66,12 +66,11 @@ void try_to_get(const char *path, int pid, time_t timestamp)
} }
sun.sun_family = AF_UNIX; sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, ":clr-debug-info"); strcpy(sun.sun_path, "/run/clr-debug-info");
sun.sun_path[0] = 0; /* anonymous unix socket */
ret = connect(sockfd, ret = connect(sockfd,
(struct sockaddr *)&sun, (struct sockaddr *)&sun,
offsetof(struct sockaddr_un, sun_path) + strlen(":clr-debug-info") + 1); offsetof(struct sockaddr_un, sun_path) + strlen("/run/clr-debug-info") + 1);
if (ret < 0) { if (ret < 0) {
printf("Cannot connect %s\n", strerror(errno)); printf("Cannot connect %s\n", strerror(errno));
close(sockfd); close(sockfd);
@@ -85,6 +84,7 @@ void try_to_get(const char *path, int pid, time_t timestamp)
if (ret == 0 && cred.pid == pid) { if (ret == 0 && cred.pid == pid) {
printf("Recursion\n"); printf("Recursion\n");
close(sockfd); close(sockfd);
return;
} }
command = NULL; command = NULL;
+1 -1
View File
@@ -113,7 +113,7 @@ bool nc_copy_file(const char *src, const char *dst, mode_t mode, bool remove_tar
while (true) { while (true) {
if ((r = read(src_fd, &buffer, sizeof(buffer))) < 0) { if ((r = read(src_fd, &buffer, sizeof(buffer))) < 0) {
ret = false; ret = false;
break; goto end;
} }
if (write(dest_fd, buffer, sizeof(buffer)) != r) { if (write(dest_fd, buffer, sizeof(buffer)) != r) {
break; break;
+7 -5
View File
@@ -123,8 +123,8 @@ static inline unsigned nc_hashmap_get_hash(NcHashmap *self, const void *key)
return hash; return hash;
} }
static bool nc_hashmap_insert_bucket(NcHashmap *self, NcHashmapEntry *buckets, int n_buckets, static int nc_hashmap_insert_bucket(NcHashmap *self, NcHashmapEntry *buckets, int n_buckets,
unsigned hash, const void *key, void *value) unsigned hash, const void *key, void *value)
{ {
NcHashmapEntry *row = &(buckets[hash % n_buckets]); NcHashmapEntry *row = &(buckets[hash % n_buckets]);
NcHashmapEntry *head = NULL; NcHashmapEntry *head = NULL;
@@ -458,10 +458,12 @@ bool nc_hashmap_iter_next(NcHashmapIter *citer, void **key, void **value)
} }
item = &(map->buckets[iter->bucket]); item = &(map->buckets[iter->bucket]);
} }
if (item && item->occ) { if (item) {
goto success; if (item->occ) {
goto success;
}
item = item->next;
} }
item = item->next;
} }
return false; return false;
+164 -25
View File
@@ -27,14 +27,17 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <grp.h>
#include <linux/capability.h>
#include <malloc.h> #include <malloc.h>
#include <pthread.h> #include <pthread.h>
#include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdatomic.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@@ -46,18 +49,24 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "systemd/sd-daemon.h"
#include "config.h"
#ifdef HAVE_ATOMIC_SUPPORT
#include <stdatomic.h>
#endif
static pthread_mutex_t dupes_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t dupes_mutex = PTHREAD_MUTEX_INITIALIZER;
char *urls[2] = { "https://debuginfo.clearlinux.org/debuginfo/", char *urls[2] = { "https://cdn.download.clearlinux.org/debuginfo/",
"https://debuginfo.clearlinux.org/debuginfo/" }; "https://cdn-alt.download.clearlinux.org/debuginfo/" };
int urlcounter = 1; int urlcounter = 1;
static NcHashmap *hash = NULL; static NcHashmap *hash = NULL;
#define MAX_CONNECTIONS 16 #define MAX_CONNECTIONS 16
static atomic_int current_connection_count = 0;
static int avoid_dupes(const char *url) static int avoid_dupes(const char *url)
{ {
int retval = 0; int retval = 0;
@@ -85,6 +94,10 @@ static int avoid_dupes(const char *url)
return retval; return retval;
} }
#ifdef HAVE_ATOMIC_SUPPORT
static atomic_int current_connection_count = 0;
/** /**
* Get the current connection count atomically * Get the current connection count atomically
*/ */
@@ -108,11 +121,52 @@ __nc_inline__ static inline void dec_connection_count(void)
{ {
atomic_fetch_sub(&current_connection_count, 1); atomic_fetch_sub(&current_connection_count, 1);
} }
#else /* HAVE_ATOMIC_SUPPORT */
static int current_connection_count = 0;
/* No stdatomic compiler support, fallback to pthread mutex (slower) */
pthread_mutex_t con_count_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Get the current connection count via mutex
*/
__nc_inline__ static inline int get_current_connection_count(void)
{
int r;
pthread_mutex_lock(&con_count_mutex);
r = current_connection_count;
pthread_mutex_unlock(&con_count_mutex);
return r;
}
/**
* Increment the connection counter via mutex
*/
__nc_inline__ static inline void inc_connection_count(void)
{
pthread_mutex_lock(&con_count_mutex);
current_connection_count++;
pthread_mutex_unlock(&con_count_mutex);
}
/**
* Decrement the connection counter via mutex
*/
__nc_inline__ static inline void dec_connection_count(void)
{
pthread_mutex_lock(&con_count_mutex);
current_connection_count--;
pthread_mutex_unlock(&con_count_mutex);
}
#endif /* !(HAVE_ATOMIC_SUPPORT) */
static int curl_get_file(const char *url, const char *prefix, time_t timestamp) static int curl_get_file(const char *url, const char *prefix, time_t timestamp)
{ {
CURLcode code; CURLcode code;
long ret; long ret;
long changed;
int fd; int fd;
char filename[PATH_MAX]; char filename[PATH_MAX];
CURL *curl = NULL; CURL *curl = NULL;
@@ -140,6 +194,22 @@ static int curl_get_file(const char *url, const char *prefix, time_t timestamp)
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
/*
* Some sane timeout values to prevent stalls
*
* Connect timeout is for first connection to the server.
* The low speed timeout is for slow downloads. Since many
* files are several mB large, we want to prevent them from
* taking forever. (1kB/sec avg over 30secs).
*/
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 30);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1024);
/* request timestamp of files from server */
curl_easy_setopt(curl, CURLOPT_FILETIME, 1);
if (timestamp) { if (timestamp) {
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
@@ -168,6 +238,17 @@ static int curl_get_file(const char *url, const char *prefix, time_t timestamp)
} }
if (ret == 200) { if (ret == 200) {
/* get timestamp, if any */
curl_easy_getinfo(curl, CURLINFO_FILETIME, &changed);
if (changed >= 0) {
struct timespec times[2];
times[0].tv_sec = (time_t)changed;
times[0].tv_nsec = 0;
times[1].tv_sec = (time_t)changed;
times[1].tv_nsec = 0;
futimens(fd, times);
}
autofree(char) *command = NULL; autofree(char) *command = NULL;
// printf("Filename is %s\n", filename); // printf("Filename is %s\n", filename);
@@ -175,7 +256,8 @@ static int curl_get_file(const char *url, const char *prefix, time_t timestamp)
stat(filename, &statbuf); stat(filename, &statbuf);
if (statbuf.st_size > 0 && if (statbuf.st_size > 0 &&
asprintf(&command, asprintf(&command,
"tar -C /var/cache/debuginfo/%s --no-same-owner -xf %s", "tar -C /var/cache/debuginfo/%s --no-same-owner "
"--no-same-permissions -xf %s",
prefix, prefix,
filename) >= 0) { filename) >= 0) {
if (system(command) != 0) { if (system(command) != 0) {
@@ -220,7 +302,6 @@ static void *server_thread(void *arg)
if (ret < 0) { if (ret < 0) {
goto thread_end; goto thread_end;
} }
prefix = buf;
c = strchr(buf, ':'); c = strchr(buf, ':');
if (!c) { if (!c) {
goto thread_end; goto thread_end;
@@ -273,6 +354,7 @@ static void *server_thread(void *arg)
} }
gettimeofday(&after, NULL); gettimeofday(&after, NULL);
#if 0
if (timedelta(before, after) > 0.6) if (timedelta(before, after) > 0.6)
printf("Request for %s took %5.2f seconds (%i - %i)\n", printf("Request for %s took %5.2f seconds (%i - %i)\n",
url, url,
@@ -280,7 +362,7 @@ static void *server_thread(void *arg)
(1.0 * after.tv_usec - before.tv_usec) / 1000000.0, (1.0 * after.tv_usec - before.tv_usec) / 1000000.0,
ret, ret,
(int)timestamp); (int)timestamp);
#endif
/* tell the other side we're done with the download */ /* tell the other side we're done with the download */
wr = write(fd, "ok", 3); wr = write(fd, "ok", 3);
@@ -298,40 +380,97 @@ int main(__nc_unused__ int argc, __nc_unused__ char **argv)
struct sockaddr_un sun; struct sockaddr_un sun;
int ret; int ret;
int curl_done = 0; int curl_done = 0;
uid_t dbg_user = 0;
gid_t dbg_group = 0;
struct passwd *passwdentry;
const char *required_paths[] = { "/var/cache/debuginfo/lib", "/var/cache/debuginfo/src" }; const char *required_paths[] = { "/var/cache/debuginfo/lib", "/var/cache/debuginfo/src" };
umask(0);
passwdentry = getpwnam("dbginfo");
if (passwdentry) {
dbg_user = passwdentry->pw_uid;
dbg_group = passwdentry->pw_gid;
}
endpwent();
if (prctl(PR_SET_DUMPABLE, 0) != 0) {
fprintf(stderr,
"Failed to disable PR_SET_DUMPABLE. Do NOT gdb attach this process: %s\n",
strerror(errno));
}
if (geteuid() == 0) {
if (prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN) != 0) {
fprintf(stderr, "Failed to drop caps: %s\n", strerror(errno));
}
}
for (size_t i = 0; i < ARRAY_SIZE(required_paths); i++) { for (size_t i = 0; i < ARRAY_SIZE(required_paths); i++) {
const char *req_path = required_paths[i]; const char *req_path = required_paths[i];
if (nc_file_exists(req_path)) { struct stat st = { .st_ino = 0 };
continue; if (lstat(req_path, &st) == 0) {
/* If the file already exists, check ownership
* and delete tree if incorrect. Essentially a
* one-off operation to transition from root owned to
* dbginfo owned */
if (st.st_uid == dbg_user) {
continue;
}
fprintf(stderr, "Removing old debug information %s\n", req_path);
nc_rm_rf(req_path);
} }
if (!nc_mkdir_p(req_path, 00755)) { if (!nc_mkdir_p(req_path, 00755)) {
fprintf(stderr, "Failed to mkdir: %s %s\n", strerror(errno), req_path); fprintf(stderr, "Failed to mkdir: %s %s\n", strerror(errno), req_path);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (chown(req_path, dbg_user, dbg_group) != 0) {
fprintf(stderr, "Failed to chown: %s %s\n", strerror(errno), req_path);
return EXIT_FAILURE;
}
} }
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sd_listen_fds(0) == 1) {
if (sockfd < 0) { /* systemd socket activation */
printf("Received socket from systemd socket activation\n");
sockfd = SD_LISTEN_FDS_START + 0;
} else if (sd_listen_fds(0) > 1) {
printf("Too many file descriptors received.\n");
exit(1);
} else {
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) {
return EXIT_FAILURE;
}
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, "/run/clr-debug-info");
ret = bind(sockfd,
(struct sockaddr *)&sun,
offsetof(struct sockaddr_un, sun_path) + strlen("/run/clr-debug-info") + 1);
if (ret < 0) {
printf("Failed to bind:%s \n", strerror(errno));
return EXIT_FAILURE;
}
if (listen(sockfd, 16) < 0) {
printf("Failed to listen:%s \n", strerror(errno));
return EXIT_FAILURE;
}
}
if (setgid(dbg_group)) {
fprintf(stderr, "Unable to drop privileges setgid %s\n", strerror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (setgroups(1, &dbg_group)) {
sun.sun_family = AF_UNIX; fprintf(stderr, "Unable to drop privileges setgroups %s\n", strerror(errno));
strcpy(sun.sun_path, ":clr-debug-info");
sun.sun_path[0] = 0; /* anonymous unix socket */
ret = bind(sockfd,
(struct sockaddr *)&sun,
offsetof(struct sockaddr_un, sun_path) + strlen(":clr-debug-info") + 1);
if (ret < 0) {
printf("Failed to bind:%s \n", strerror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (setuid(dbg_user)) {
if (listen(sockfd, 16) < 0) { fprintf(stderr, "Unable to drop privileges setuid %s\n", strerror(errno));
printf("Failed to listen:%s \n", strerror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} }