public inbox for util-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] uuidd: refactoring & systemd support (take 2)
@ 2012-05-03 19:01 Petr Uzel
  2012-05-03 19:01 ` [PATCH 01/15] uuidd: use UUIDD_OP_GETPID instead of magic number Petr Uzel
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Hi all.

This is the second version of uuidd refactoring and systemd support. First
version was posted at [1]

The primary goal of the patch series below was to implement systemd support in
for uuidd as it was one of the items on Karel's wish list for util-linux-2.22 [2].

First two patches are just minor cleanups I came across while working on the code.

Then I added --no-pid, --no-fork and --socket-activation options
to make uuidd play nicely with systemd (or any compatible init system should
there be any).  Note that --socket-activation automatically implies all other
mentioned options. With the socket activation mode [3], uuidd is started on
demand when the first request comes to its request socket and quits after 60
seconds of inactivity (can be overridden in the provided unit files).

To make socket-activation work, the uuidd has to be compiled with the
sd-daemon.c files.  This is controlled via the --enable-socket-activation
configure option. The second alternative would be to link with libsystemd
shared library, but after discussion with Karel I decided not to do it to avoid
some build dependency cycles between systemd and util-linux (to make life
easier for distributions).

This series also removes the ability of libuuid to execute uuidd daemon
on-demand if it is not running as we believe that it is not an elegant solution
and it should be rather required that the daemon is started by an initscript or
activated via the socket.

Regarding the last patch in the series, it addresses issue described in
http://marc.info/?l=util-linux-ng&m=133405763330121&w=2 in the way recomended
by Karel. However, after implementing it, I'm wondering: wouldn't it be cleaner
to just test if /dev/u?random exists and is readable in uuid_generate() instead
of calling random_get_fd() and passing the fd down the stack?


For reference, these are the important changes since first version of the series:

- do not implement --keep-privs and instead remove the privilege-dropping
  functionality completely
- removed ability to execute uuidd from libuuid
- server_loop() has been refactored not to use confusing goto statement
- long list of arguments of server_loop() has been avoided by
  encapsulating them in uuidd_ctx structure
- s/--enable-uuidd-socket-activation/--enable-socket-activation
- s/UUIDD_SOCKET_ACTIVATION/USE_SOCKET_ACTIVATION
- no longer mention configure option names in the uuidd manpage
- this series no longer include build-sys fixes (posted as separate series)


Thank you in advance for any feedback and comments.

Thanks,

	Petr

[1] http://marc.info/?l=util-linux-ng&m=133303960414089&w=2
[2] http://www.spinics.net/lists/util-linux-ng/msg05793.html
[3] http://0pointer.de/blog/projects/socket-activation.html



Petr Uzel (15):
  uuidd: use UUIDD_OP_GETPID instead of magic number
  uuidd: remove useless initialization of cleanup_socket
  uuidd: factor out pidfile creation into separate function
  uuidd: implement --no-pid option
  uuidd: use ignore_result helper
  uuidd: implement --no-fork option
  uuidd: factor out socket creation into separate function
  uuidd: implement --socket-activation option
  uuidd: print all debugging information to stderr
  uuidd: do not drop privileges
  libuuid: use EXIT_FAILURE
  uuidd: add systemd unit files
  libuuid: don't exec uuidd
  uuidd: introduce uuidd_cxt to pass arguments to server loop
  libuuid: avoid double open and leaking descriptor

 Makefile.am                 |    3 +-
 configure.ac                |   23 ++
 fdisk/fdiskdoslabel.c       |    2 +-
 include/randutils.h         |    2 +-
 lib/randutils.c             |    8 +-
 libuuid/src/Makefile.am     |    1 -
 libuuid/src/gen_uuid.c      |   65 +-----
 libuuid/src/uuidd.h         |    2 +-
 misc-utils/.gitignore       |    1 +
 misc-utils/Makefile.am      |   17 ++-
 misc-utils/sd-daemon.c      |  530 +++++++++++++++++++++++++++++++++++++++++++
 misc-utils/sd-daemon.h      |  282 +++++++++++++++++++++++
 misc-utils/uuidd.8          |   12 +
 misc-utils/uuidd.c          |  313 +++++++++++++++++---------
 misc-utils/uuidd.service.in |    9 +
 misc-utils/uuidd.socket     |    8 +
 16 files changed, 1109 insertions(+), 169 deletions(-)
 create mode 100644 misc-utils/sd-daemon.c
 create mode 100644 misc-utils/sd-daemon.h
 create mode 100644 misc-utils/uuidd.service.in
 create mode 100644 misc-utils/uuidd.socket

-- 
1.7.7


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/15] uuidd: use UUIDD_OP_GETPID instead of magic number
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 02/15] uuidd: remove useless initialization of cleanup_socket Petr Uzel
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Make parameters passed to call_daemon() more descriptive:
- use UUIDD_OP_GETPID instead of magic number 0
- call_daemon() takes pointer as a last argument, so pass NULL instead
  of 0

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 7c19615..80600f1 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -244,7 +244,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			fprintf(stderr, _("Failed to lock %s: %m\n"), pidfile_path);
 		exit(EXIT_FAILURE);
 	}
-	ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
+	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
 	if (ret > 0) {
 		if (!quiet)
 			printf(_("uuidd daemon already running at pid %s\n"),
@@ -578,7 +578,7 @@ int main(int argc, char **argv)
 	}
 
 	if (do_kill) {
-		ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
+		ret = call_daemon(socket_path, UUIDD_OP_GETPID, buf, sizeof(buf), 0, NULL);
 		if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
 			ret = kill(do_kill, SIGTERM);
 			if (ret < 0) {
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/15] uuidd: remove useless initialization of cleanup_socket
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
  2012-05-03 19:01 ` [PATCH 01/15] uuidd: use UUIDD_OP_GETPID instead of magic number Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 03/15] uuidd: factor out pidfile creation into separate function Petr Uzel
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 80600f1..0d844fb 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -229,7 +229,6 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		exit(EXIT_FAILURE);
 	}
 	cleanup_pidfile = pidfile_path;
-	cleanup_socket = 0;
 	signal(SIGALRM, terminate_intr);
 	alarm(30);
 	fl.l_type = F_WRLCK;
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/15] uuidd: factor out pidfile creation into separate function
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
  2012-05-03 19:01 ` [PATCH 01/15] uuidd: use UUIDD_OP_GETPID instead of magic number Petr Uzel
  2012-05-03 19:01 ` [PATCH 02/15] uuidd: remove useless initialization of cleanup_socket Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 04/15] uuidd: implement --no-pid option Petr Uzel
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Introduce create_pidfile() function.

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |   48 ++++++++++++++++++++++++++++++++++--------------
 1 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 0d844fb..704c9e9 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -207,19 +207,18 @@ static int call_daemon(const char *socket_path, int op, char *buf,
 	return ret;
 }
 
-static void server_loop(const char *socket_path, const char *pidfile_path,
-			int debug, int timeout, int quiet)
+/*
+ * Exclusively create and open a pid file with path @pidfile_path
+ *
+ * Set cleanup_pidfile global variable for the cleanup
+ * handler. @pidfile_path must not be NULL.
+ *
+ * Return file descriptor of the created pid_file.
+ */
+static int create_pidfile(const char *pidfile_path, int quiet)
 {
-	struct sockaddr_un	my_addr, from_addr;
-	struct flock		fl;
-	socklen_t		fromlen;
-	int32_t			reply_len = 0;
-	uuid_t			uu;
-	mode_t			save_umask;
-	char			reply_buf[1024], *cp;
-	char			op, str[UUID_STR_LEN];
-	int			i, s, ns, len, num;
-	int			fd_pidfile, ret;
+	int		fd_pidfile;
+	struct flock	fl;
 
 	fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
 	if (fd_pidfile < 0) {
@@ -229,8 +228,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		exit(EXIT_FAILURE);
 	}
 	cleanup_pidfile = pidfile_path;
-	signal(SIGALRM, terminate_intr);
-	alarm(30);
+
 	fl.l_type = F_WRLCK;
 	fl.l_whence = SEEK_SET;
 	fl.l_start = 0;
@@ -243,6 +241,28 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			fprintf(stderr, _("Failed to lock %s: %m\n"), pidfile_path);
 		exit(EXIT_FAILURE);
 	}
+
+	return fd_pidfile;
+}
+
+static void server_loop(const char *socket_path, const char *pidfile_path,
+			int debug, int timeout, int quiet)
+{
+	struct sockaddr_un	my_addr, from_addr;
+	socklen_t		fromlen;
+	int32_t			reply_len = 0;
+	uuid_t			uu;
+	mode_t			save_umask;
+	char			reply_buf[1024], *cp;
+	char			op, str[UUID_STR_LEN];
+	int			i, s, ns, len, num;
+	int			fd_pidfile, ret;
+
+	signal(SIGALRM, terminate_intr);
+	alarm(30);
+
+	fd_pidfile = create_pidfile(pidfile_path, quiet);
+
 	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
 	if (ret > 0) {
 		if (!quiet)
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/15] uuidd: implement --no-pid option
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (2 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 03/15] uuidd: factor out pidfile creation into separate function Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 05/15] uuidd: use ignore_result helper Petr Uzel
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

With this option, uuidd does not create the PID file.

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.8 |    3 +++
 misc-utils/uuidd.c |   48 ++++++++++++++++++++++++++++++++++++------------
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/misc-utils/uuidd.8 b/misc-utils/uuidd.8
index 8e82b10..07e533b 100644
--- a/misc-utils/uuidd.8
+++ b/misc-utils/uuidd.8
@@ -36,6 +36,9 @@ UUIDs.
 Specify the pathname where the pid file should be written.  By default,
 the pid file is written to /var/run/uuidd/uuidd.pid.
 .TP
+.BR \-P , " \-\-no-pid "
+Do not create pid file.
+.TP
 .B \-q
 Suppress some failure messages.
 .TP
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 704c9e9..be3e3cf 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -64,6 +64,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 		" -r, --random        test random-based generation\n"
 		" -t, --time          test time-based generation\n"
 		" -n, --uuids <num>   request number of uuids\n"
+		" -P, --no-pid        do not create pid file\n"
 		" -d, --debug         run in debugging mode\n"
 		" -q, --quiet         turn on quiet mode\n"
 		" -V, --version       output version information and exit\n"
@@ -112,7 +113,8 @@ static const char *cleanup_pidfile, *cleanup_socket;
 
 static void terminate_intr(int signo CODE_ATTR((unused)))
 {
-	unlink(cleanup_pidfile);
+	if (cleanup_pidfile)
+		unlink(cleanup_pidfile);
 	if (cleanup_socket)
 		unlink(cleanup_socket);
 	exit(EXIT_SUCCESS);
@@ -256,12 +258,14 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	char			reply_buf[1024], *cp;
 	char			op, str[UUID_STR_LEN];
 	int			i, s, ns, len, num;
-	int			fd_pidfile, ret;
+	int			fd_pidfile = -1;
+	int			ret;
 
 	signal(SIGALRM, terminate_intr);
 	alarm(30);
 
-	fd_pidfile = create_pidfile(pidfile_path, quiet);
+	if (pidfile_path)
+		fd_pidfile = create_pidfile(pidfile_path, quiet);
 
 	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
 	if (ret > 0) {
@@ -321,13 +325,15 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	signal(SIGALRM, terminate_intr);
 	signal(SIGPIPE, SIG_IGN);
 
-	sprintf(reply_buf, "%8d\n", getpid());
-	if (ftruncate(fd_pidfile, 0)) {
-		/* Silence warn_unused_result */
+	if (pidfile_path) {
+		sprintf(reply_buf, "%8d\n", getpid());
+		if (ftruncate(fd_pidfile, 0)) {
+			/* Silence warn_unused_result */
+		}
+		write_all(fd_pidfile, reply_buf, strlen(reply_buf));
+		if (fd_pidfile > 1)
+			close(fd_pidfile); /* Unlock the pid file */
 	}
-	write_all(fd_pidfile, reply_buf, strlen(reply_buf));
-	if (fd_pidfile > 1)
-		close(fd_pidfile); /* Unlock the pid file */
 
 	while (1) {
 		fromlen = sizeof(from_addr);
@@ -446,7 +452,8 @@ static void __attribute__ ((__noreturn__)) unexpected_size(int size)
 int main(int argc, char **argv)
 {
 	const char	*socket_path = UUIDD_SOCKET_PATH;
-	const char	*pidfile_path = UUIDD_PIDFILE_PATH;
+	const char	*pidfile_path = NULL;
+	const char	*pidfile_path_param = NULL;
 	const char	*err_context;
 	char		buf[1024], *cp;
 	char		str[UUID_STR_LEN], *tmp;
@@ -456,6 +463,7 @@ int main(int argc, char **argv)
 	int		i, c, ret;
 	int		debug = 0, do_type = 0, do_kill = 0, num = 0;
 	int		timeout = 0, quiet = 0, drop_privs = 0;
+	int		no_pid = 0;
 
 	static const struct option longopts[] = {
 		{"pid", required_argument, NULL, 'p'},
@@ -465,6 +473,7 @@ int main(int argc, char **argv)
 		{"random", no_argument, NULL, 'r'},
 		{"time", no_argument, NULL, 't'},
 		{"uuids", required_argument, NULL, 'n'},
+		{"no-pid", no_argument, NULL, 'P'},
 		{"debug", no_argument, NULL, 'd'},
 		{"quiet", no_argument, NULL, 'q'},
 		{"version", no_argument, NULL, 'V'},
@@ -478,7 +487,7 @@ int main(int argc, char **argv)
 	atexit(close_stdout);
 
 	while ((c =
-		getopt_long(argc, argv, "p:s:T:krtn:dqVh", longopts,
+		getopt_long(argc, argv, "p:s:T:krtn:PdqVh", longopts,
 			    NULL)) != -1) {
 		switch (c) {
 		case 'd':
@@ -497,7 +506,11 @@ int main(int argc, char **argv)
 			}
 			break;
 		case 'p':
-			pidfile_path = optarg;
+			pidfile_path_param = optarg;
+			drop_privs = 1;
+			break;
+		case 'P':
+			no_pid = 1;
 			drop_privs = 1;
 			break;
 		case 'q':
@@ -533,6 +546,17 @@ int main(int argc, char **argv)
 			usage(stderr);
 		}
 	}
+
+	if (no_pid && pidfile_path_param && !quiet)
+		fprintf(stderr, _("Both --pid and --no-pid specified. "
+				  "Ignoring --no-pid.\n"));
+
+	if (!no_pid && !pidfile_path_param)
+		pidfile_path = UUIDD_PIDFILE_PATH;
+	else if (pidfile_path_param)
+		pidfile_path = pidfile_path_param;
+
+
 	uid = getuid();
 	if (uid && drop_privs) {
 		gid = getgid();
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/15] uuidd: use ignore_result helper
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (3 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 04/15] uuidd: implement --no-pid option Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 06/15] uuidd: implement --no-fork option Petr Uzel
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index be3e3cf..50ae61f 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -34,6 +34,7 @@ extern int optind;
 #include "uuid.h"
 #include "uuidd.h"
 #include "writeall.h"
+#include "c.h"
 
 #include "closestream.h"
 #include "nls.h"
@@ -327,9 +328,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 
 	if (pidfile_path) {
 		sprintf(reply_buf, "%8d\n", getpid());
-		if (ftruncate(fd_pidfile, 0)) {
-			/* Silence warn_unused_result */
-		}
+		ignore_result( ftruncate(fd_pidfile, 0) );
 		write_all(fd_pidfile, reply_buf, strlen(reply_buf));
 		if (fd_pidfile > 1)
 			close(fd_pidfile); /* Unlock the pid file */
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/15] uuidd: implement --no-fork option
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (4 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 05/15] uuidd: use ignore_result helper Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 07/15] uuidd: factor out socket creation into separate function Petr Uzel
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

With this option, uuidd does not daemonize itself but stays
in the foreground.

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.8 |    3 +++
 misc-utils/uuidd.c |   18 ++++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/misc-utils/uuidd.8 b/misc-utils/uuidd.8
index 07e533b..e3ccf6f 100644
--- a/misc-utils/uuidd.8
+++ b/misc-utils/uuidd.8
@@ -39,6 +39,9 @@ the pid file is written to /var/run/uuidd/uuidd.pid.
 .BR \-P , " \-\-no-pid "
 Do not create pid file.
 .TP
+.BR \-F , " \-\-no-fork "
+Do not daemonize using double-fork.
+.TP
 .B \-q
 Suppress some failure messages.
 .TP
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 50ae61f..5e86077 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -66,6 +66,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 		" -t, --time          test time-based generation\n"
 		" -n, --uuids <num>   request number of uuids\n"
 		" -P, --no-pid        do not create pid file\n"
+		" -F, --no-fork       do not daemonize using double-fork\n"
 		" -d, --debug         run in debugging mode\n"
 		" -q, --quiet         turn on quiet mode\n"
 		" -V, --version       output version information and exit\n"
@@ -249,7 +250,7 @@ static int create_pidfile(const char *pidfile_path, int quiet)
 }
 
 static void server_loop(const char *socket_path, const char *pidfile_path,
-			int debug, int timeout, int quiet)
+			int debug, int timeout, int quiet, int no_fork)
 {
 	struct sockaddr_un	my_addr, from_addr;
 	socklen_t		fromlen;
@@ -287,7 +288,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	 * Make sure the socket isn't using fd numbers 0-2 to avoid it
 	 * getting closed by create_daemon()
 	 */
-	while (!debug && s <= 2) {
+	while ((!debug || no_fork) && s <= 2) {
 		s = dup(s);
 		if (s < 0)
 			err(EXIT_FAILURE, "dup");
@@ -318,7 +319,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	}
 
 	cleanup_socket = socket_path;
-	if (!debug)
+	if (!debug && !no_fork)
 		create_daemon();
 	signal(SIGHUP, terminate_intr);
 	signal(SIGINT, terminate_intr);
@@ -462,7 +463,7 @@ int main(int argc, char **argv)
 	int		i, c, ret;
 	int		debug = 0, do_type = 0, do_kill = 0, num = 0;
 	int		timeout = 0, quiet = 0, drop_privs = 0;
-	int		no_pid = 0;
+	int		no_pid = 0, no_fork = 0;
 
 	static const struct option longopts[] = {
 		{"pid", required_argument, NULL, 'p'},
@@ -473,6 +474,7 @@ int main(int argc, char **argv)
 		{"time", no_argument, NULL, 't'},
 		{"uuids", required_argument, NULL, 'n'},
 		{"no-pid", no_argument, NULL, 'P'},
+		{"no-fork", no_argument, NULL, 'F'},
 		{"debug", no_argument, NULL, 'd'},
 		{"quiet", no_argument, NULL, 'q'},
 		{"version", no_argument, NULL, 'V'},
@@ -486,7 +488,7 @@ int main(int argc, char **argv)
 	atexit(close_stdout);
 
 	while ((c =
-		getopt_long(argc, argv, "p:s:T:krtn:PdqVh", longopts,
+		getopt_long(argc, argv, "p:s:T:krtn:PFdqVh", longopts,
 			    NULL)) != -1) {
 		switch (c) {
 		case 'd':
@@ -512,6 +514,10 @@ int main(int argc, char **argv)
 			no_pid = 1;
 			drop_privs = 1;
 			break;
+		case 'F':
+			no_fork = 1;
+			drop_privs = 1;
+			break;
 		case 'q':
 			quiet++;
 			break;
@@ -637,6 +643,6 @@ int main(int argc, char **argv)
 		return EXIT_SUCCESS;
 	}
 
-	server_loop(socket_path, pidfile_path, debug, timeout, quiet);
+	server_loop(socket_path, pidfile_path, debug, timeout, quiet, no_fork);
 	return EXIT_SUCCESS;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/15] uuidd: factor out socket creation into separate function
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (5 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 06/15] uuidd: implement --no-fork option Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 08/15] uuidd: implement --socket-activation option Petr Uzel
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |   74 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 5e86077..0ea6288 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -249,34 +249,20 @@ static int create_pidfile(const char *pidfile_path, int quiet)
 	return fd_pidfile;
 }
 
-static void server_loop(const char *socket_path, const char *pidfile_path,
-			int debug, int timeout, int quiet, int no_fork)
+/*
+ * Create AF_UNIX, SOCK_STREAM socket and bind to @socket_path
+ *
+ * If @will_fork is true, then make sure the descriptor
+ * of the socket is >2, so that it wont be later closed
+ * during create_daemon().
+ *
+ * Return file descriptor corresponding to created socket.
+ */
+static int create_socket(const char *socket_path, int will_fork, int quiet)
 {
-	struct sockaddr_un	my_addr, from_addr;
-	socklen_t		fromlen;
-	int32_t			reply_len = 0;
-	uuid_t			uu;
+	struct sockaddr_un	my_addr;
 	mode_t			save_umask;
-	char			reply_buf[1024], *cp;
-	char			op, str[UUID_STR_LEN];
-	int			i, s, ns, len, num;
-	int			fd_pidfile = -1;
-	int			ret;
-
-	signal(SIGALRM, terminate_intr);
-	alarm(30);
-
-	if (pidfile_path)
-		fd_pidfile = create_pidfile(pidfile_path, quiet);
-
-	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
-	if (ret > 0) {
-		if (!quiet)
-			printf(_("uuidd daemon already running at pid %s\n"),
-			       reply_buf);
-		exit(EXIT_FAILURE);
-	}
-	alarm(0);
+	int 			s;
 
 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
 		if (!quiet)
@@ -288,7 +274,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	 * Make sure the socket isn't using fd numbers 0-2 to avoid it
 	 * getting closed by create_daemon()
 	 */
-	while ((!debug || no_fork) && s <= 2) {
+	while (will_fork && s <= 2) {
 		s = dup(s);
 		if (s < 0)
 			err(EXIT_FAILURE, "dup");
@@ -310,7 +296,40 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		exit(EXIT_FAILURE);
 	}
 	umask(save_umask);
+	cleanup_socket = socket_path;
 
+	return s;
+}
+
+static void server_loop(const char *socket_path, const char *pidfile_path,
+			int debug, int timeout, int quiet, int no_fork)
+{
+	struct sockaddr_un	from_addr;
+	socklen_t		fromlen;
+	int32_t			reply_len = 0;
+	uuid_t			uu;
+	char			reply_buf[1024], *cp;
+	char			op, str[UUID_STR_LEN];
+	int			i, s, ns, len, num;
+	int			fd_pidfile = -1;
+	int			ret;
+
+	signal(SIGALRM, terminate_intr);
+	alarm(30);
+
+	if (pidfile_path)
+		fd_pidfile = create_pidfile(pidfile_path, quiet);
+
+	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
+	if (ret > 0) {
+		if (!quiet)
+			printf(_("uuidd daemon already running at pid %s\n"),
+			       reply_buf);
+		exit(EXIT_FAILURE);
+	}
+	alarm(0);
+
+	s = create_socket(socket_path, (!debug || !no_fork), quiet);
 	if (listen(s, SOMAXCONN) < 0) {
 		if (!quiet)
 			fprintf(stderr, _("Couldn't listen on unix "
@@ -318,7 +337,6 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		exit(EXIT_FAILURE);
 	}
 
-	cleanup_socket = socket_path;
 	if (!debug && !no_fork)
 		create_daemon();
 	signal(SIGHUP, terminate_intr);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/15] uuidd: implement --socket-activation option
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (6 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 07/15] uuidd: factor out socket creation into separate function Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 09/15] uuidd: print all debugging information to stderr Petr Uzel
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Implement --socket-activation option, which is supposed to be used
with systemd (or equivalent init system) socket activation mechanism.
With this option, the UUID daemon does not create the socket on its own,
but instead expect the connection fd to be provided by the calling
process.

This option is only available if util-linux is configured with
--enable-socket-activation option. With this configure
option, the uuidd is compiled with sd-daemon.c.

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 configure.ac           |   12 +
 misc-utils/Makefile.am |    6 +
 misc-utils/sd-daemon.c |  530 ++++++++++++++++++++++++++++++++++++++++++++++++
 misc-utils/sd-daemon.h |  282 +++++++++++++++++++++++++
 misc-utils/uuidd.8     |    6 +
 misc-utils/uuidd.c     |  134 ++++++++----
 6 files changed, 926 insertions(+), 44 deletions(-)
 create mode 100644 misc-utils/sd-daemon.c
 create mode 100644 misc-utils/sd-daemon.h

diff --git a/configure.ac b/configure.ac
index 56f378e..f5f3a2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1123,6 +1123,18 @@ if test "x$enable_login_chown_vcs" = xyes; then
 fi
 
 
+AC_ARG_ENABLE([socket-activation],
+  AS_HELP_STRING([--enable-socket-activation], [build uuidd with support for systemd socket activation]),
+  [], enable_socket_activation=no
+)
+
+AM_CONDITIONAL(USE_SOCKET_ACTIVATION, test "x$enable_socket_activation" = xyes)
+
+if test "x$enable_socket_activation" = xyes; then
+  AC_DEFINE(USE_SOCKET_ACTIVATION, 1, [Should uuidd support socket activation?])
+fi
+
+
 AC_ARG_ENABLE([login-stat-mail],
   AS_HELP_STRING([--enable-login-stat-mail], [let login stat() the mailbox]),
   [], enable_login_stat_mail=no
diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am
index 51f20ca..47a639b 100644
--- a/misc-utils/Makefile.am
+++ b/misc-utils/Makefile.am
@@ -83,6 +83,12 @@ usrsbin_exec_PROGRAMS += uuidd
 dist_man_MANS += uuidd.8
 uuidd_LDADD = $(ul_libuuid_la)
 uuidd_CFLAGS = $(AM_CFLAGS) -I$(ul_libuuid_srcdir)
+uuidd_SOURCES = \
+	uuidd.c
+if USE_SOCKET_ACTIVATION
+uuidd_SOURCES += sd-daemon.c
+uuidd_LDADD += -lrt
+endif
 endif
 
 if BUILD_LIBBLKID
diff --git a/misc-utils/sd-daemon.c b/misc-utils/sd-daemon.c
new file mode 100644
index 0000000..763e079
--- /dev/null
+++ b/misc-utils/sd-daemon.c
@@ -0,0 +1,530 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#ifdef __BIONIC__
+#include <linux/fcntl.h>
+#else
+#include <sys/fcntl.h>
+#endif
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <limits.h>
+
+#if defined(__linux__)
+#include <mqueue.h>
+#endif
+
+#include "sd-daemon.h"
+
+#if (__GNUC__ >= 4)
+#ifdef SD_EXPORT_SYMBOLS
+/* Export symbols */
+#define _sd_export_ __attribute__ ((visibility("default")))
+#else
+/* Don't export the symbols */
+#define _sd_export_ __attribute__ ((visibility("hidden")))
+#endif
+#else
+#define _sd_export_
+#endif
+
+_sd_export_ int sd_listen_fds(int unset_environment) {
+
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+        int r, fd;
+        const char *e;
+        char *p = NULL;
+        unsigned long l;
+
+        if (!(e = getenv("LISTEN_PID"))) {
+                r = 0;
+                goto finish;
+        }
+
+        errno = 0;
+        l = strtoul(e, &p, 10);
+
+        if (errno != 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        if (!p || *p || l <= 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        /* Is this for us? */
+        if (getpid() != (pid_t) l) {
+                r = 0;
+                goto finish;
+        }
+
+        if (!(e = getenv("LISTEN_FDS"))) {
+                r = 0;
+                goto finish;
+        }
+
+        errno = 0;
+        l = strtoul(e, &p, 10);
+
+        if (errno != 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        if (!p || *p) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
+                int flags;
+
+                if ((flags = fcntl(fd, F_GETFD)) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                if (flags & FD_CLOEXEC)
+                        continue;
+
+                if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+        }
+
+        r = (int) l;
+
+finish:
+        if (unset_environment) {
+                unsetenv("LISTEN_PID");
+                unsetenv("LISTEN_FDS");
+        }
+
+        return r;
+#endif
+}
+
+_sd_export_ int sd_is_fifo(int fd, const char *path) {
+        struct stat st_fd;
+
+        if (fd < 0)
+                return -EINVAL;
+
+        memset(&st_fd, 0, sizeof(st_fd));
+        if (fstat(fd, &st_fd) < 0)
+                return -errno;
+
+        if (!S_ISFIFO(st_fd.st_mode))
+                return 0;
+
+        if (path) {
+                struct stat st_path;
+
+                memset(&st_path, 0, sizeof(st_path));
+                if (stat(path, &st_path) < 0) {
+
+                        if (errno == ENOENT || errno == ENOTDIR)
+                                return 0;
+
+                        return -errno;
+                }
+
+                return
+                        st_path.st_dev == st_fd.st_dev &&
+                        st_path.st_ino == st_fd.st_ino;
+        }
+
+        return 1;
+}
+
+_sd_export_ int sd_is_special(int fd, const char *path) {
+        struct stat st_fd;
+
+        if (fd < 0)
+                return -EINVAL;
+
+        if (fstat(fd, &st_fd) < 0)
+                return -errno;
+
+        if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
+                return 0;
+
+        if (path) {
+                struct stat st_path;
+
+                if (stat(path, &st_path) < 0) {
+
+                        if (errno == ENOENT || errno == ENOTDIR)
+                                return 0;
+
+                        return -errno;
+                }
+
+                if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
+                        return
+                                st_path.st_dev == st_fd.st_dev &&
+                                st_path.st_ino == st_fd.st_ino;
+                else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
+                        return st_path.st_rdev == st_fd.st_rdev;
+                else
+                        return 0;
+        }
+
+        return 1;
+}
+
+static int sd_is_socket_internal(int fd, int type, int listening) {
+        struct stat st_fd;
+
+        if (fd < 0 || type < 0)
+                return -EINVAL;
+
+        if (fstat(fd, &st_fd) < 0)
+                return -errno;
+
+        if (!S_ISSOCK(st_fd.st_mode))
+                return 0;
+
+        if (type != 0) {
+                int other_type = 0;
+                socklen_t l = sizeof(other_type);
+
+                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
+                        return -errno;
+
+                if (l != sizeof(other_type))
+                        return -EINVAL;
+
+                if (other_type != type)
+                        return 0;
+        }
+
+        if (listening >= 0) {
+                int accepting = 0;
+                socklen_t l = sizeof(accepting);
+
+                if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
+                        return -errno;
+
+                if (l != sizeof(accepting))
+                        return -EINVAL;
+
+                if (!accepting != !listening)
+                        return 0;
+        }
+
+        return 1;
+}
+
+union sockaddr_union {
+        struct sockaddr sa;
+        struct sockaddr_in in4;
+        struct sockaddr_in6 in6;
+        struct sockaddr_un un;
+        struct sockaddr_storage storage;
+};
+
+_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) {
+        int r;
+
+        if (family < 0)
+                return -EINVAL;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        if (family > 0) {
+                union sockaddr_union sockaddr;
+                socklen_t l;
+
+                memset(&sockaddr, 0, sizeof(sockaddr));
+                l = sizeof(sockaddr);
+
+                if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                        return -errno;
+
+                if (l < sizeof(sa_family_t))
+                        return -EINVAL;
+
+                return sockaddr.sa.sa_family == family;
+        }
+
+        return 1;
+}
+
+_sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
+        union sockaddr_union sockaddr;
+        socklen_t l;
+        int r;
+
+        if (family != 0 && family != AF_INET && family != AF_INET6)
+                return -EINVAL;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        l = sizeof(sockaddr);
+
+        if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                return -errno;
+
+        if (l < sizeof(sa_family_t))
+                return -EINVAL;
+
+        if (sockaddr.sa.sa_family != AF_INET &&
+            sockaddr.sa.sa_family != AF_INET6)
+                return 0;
+
+        if (family > 0)
+                if (sockaddr.sa.sa_family != family)
+                        return 0;
+
+        if (port > 0) {
+                if (sockaddr.sa.sa_family == AF_INET) {
+                        if (l < sizeof(struct sockaddr_in))
+                                return -EINVAL;
+
+                        return htons(port) == sockaddr.in4.sin_port;
+                } else {
+                        if (l < sizeof(struct sockaddr_in6))
+                                return -EINVAL;
+
+                        return htons(port) == sockaddr.in6.sin6_port;
+                }
+        }
+
+        return 1;
+}
+
+_sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
+        union sockaddr_union sockaddr;
+        socklen_t l;
+        int r;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        l = sizeof(sockaddr);
+
+        if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                return -errno;
+
+        if (l < sizeof(sa_family_t))
+                return -EINVAL;
+
+        if (sockaddr.sa.sa_family != AF_UNIX)
+                return 0;
+
+        if (path) {
+                if (length <= 0)
+                        length = strlen(path);
+
+                if (length <= 0)
+                        /* Unnamed socket */
+                        return l == offsetof(struct sockaddr_un, sun_path);
+
+                if (path[0])
+                        /* Normal path socket */
+                        return
+                                (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
+                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
+                else
+                        /* Abstract namespace socket */
+                        return
+                                (l == offsetof(struct sockaddr_un, sun_path) + length) &&
+                                memcmp(path, sockaddr.un.sun_path, length) == 0;
+        }
+
+        return 1;
+}
+
+_sd_export_ int sd_is_mq(int fd, const char *path) {
+#if !defined(__linux__)
+        return 0;
+#else
+        struct mq_attr attr;
+
+        if (fd < 0)
+                return -EINVAL;
+
+        if (mq_getattr(fd, &attr) < 0)
+                return -errno;
+
+        if (path) {
+                char fpath[PATH_MAX];
+                struct stat a, b;
+
+                if (path[0] != '/')
+                        return -EINVAL;
+
+                if (fstat(fd, &a) < 0)
+                        return -errno;
+
+                strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
+                fpath[sizeof(fpath)-1] = 0;
+
+                if (stat(fpath, &b) < 0)
+                        return -errno;
+
+                if (a.st_dev != b.st_dev ||
+                    a.st_ino != b.st_ino)
+                        return 0;
+        }
+
+        return 1;
+#endif
+}
+
+_sd_export_ int sd_notify(int unset_environment, const char *state) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
+        return 0;
+#else
+        int fd = -1, r;
+        struct msghdr msghdr;
+        struct iovec iovec;
+        union sockaddr_union sockaddr;
+        const char *e;
+
+        if (!state) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (!(e = getenv("NOTIFY_SOCKET")))
+                return 0;
+
+        /* Must be an abstract socket, or an absolute path */
+        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        sockaddr.sa.sa_family = AF_UNIX;
+        strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
+
+        if (sockaddr.un.sun_path[0] == '@')
+                sockaddr.un.sun_path[0] = 0;
+
+        memset(&iovec, 0, sizeof(iovec));
+        iovec.iov_base = (char*) state;
+        iovec.iov_len = strlen(state);
+
+        memset(&msghdr, 0, sizeof(msghdr));
+        msghdr.msg_name = &sockaddr;
+        msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
+
+        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
+                msghdr.msg_namelen = sizeof(struct sockaddr_un);
+
+        msghdr.msg_iov = &iovec;
+        msghdr.msg_iovlen = 1;
+
+        if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        r = 1;
+
+finish:
+        if (unset_environment)
+                unsetenv("NOTIFY_SOCKET");
+
+        if (fd >= 0)
+                close(fd);
+
+        return r;
+#endif
+}
+
+_sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+        va_list ap;
+        char *p = NULL;
+        int r;
+
+        va_start(ap, format);
+        r = vasprintf(&p, format, ap);
+        va_end(ap);
+
+        if (r < 0 || !p)
+                return -ENOMEM;
+
+        r = sd_notify(unset_environment, p);
+        free(p);
+
+        return r;
+#endif
+}
+
+_sd_export_ int sd_booted(void) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+
+        struct stat a, b;
+
+        /* We simply test whether the systemd cgroup hierarchy is
+         * mounted */
+
+        if (lstat("/sys/fs/cgroup", &a) < 0)
+                return 0;
+
+        if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
+                return 0;
+
+        return a.st_dev != b.st_dev;
+#endif
+}
diff --git a/misc-utils/sd-daemon.h b/misc-utils/sd-daemon.h
new file mode 100644
index 0000000..fe51159
--- /dev/null
+++ b/misc-utils/sd-daemon.h
@@ -0,0 +1,282 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosddaemonhfoo
+#define foosddaemonhfoo
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  Reference implementation of a few systemd related interfaces for
+  writing daemons. These interfaces are trivial to implement. To
+  simplify porting we provide this reference implementation.
+  Applications are welcome to reimplement the algorithms described
+  here if they do not want to include these two source files.
+
+  The following functionality is provided:
+
+  - Support for logging with log levels on stderr
+  - File descriptor passing for socket-based activation
+  - Daemon startup and status notification
+  - Detection of systemd boots
+
+  You may compile this with -DDISABLE_SYSTEMD to disable systemd
+  support. This makes all those calls NOPs that are directly related to
+  systemd (i.e. only sd_is_xxx() will stay useful).
+
+  Since this is drop-in code we don't want any of our symbols to be
+  exported in any case. Hence we declare hidden visibility for all of
+  them.
+
+  You may find an up-to-date version of these source files online:
+
+  http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h
+  http://cgit.freedesktop.org/systemd/systemd/plain/src/sd-daemon.c
+
+  This should compile on non-Linux systems, too, but with the
+  exception of the sd_is_xxx() calls all functions will become NOPs.
+
+  See sd-daemon(7) for more information.
+*/
+
+#ifndef _sd_printf_attr_
+#if __GNUC__ >= 4
+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define _sd_printf_attr_(a,b)
+#endif
+#endif
+
+/*
+  Log levels for usage on stderr:
+
+          fprintf(stderr, SD_NOTICE "Hello World!\n");
+
+  This is similar to printk() usage in the kernel.
+*/
+#define SD_EMERG   "<0>"  /* system is unusable */
+#define SD_ALERT   "<1>"  /* action must be taken immediately */
+#define SD_CRIT    "<2>"  /* critical conditions */
+#define SD_ERR     "<3>"  /* error conditions */
+#define SD_WARNING "<4>"  /* warning conditions */
+#define SD_NOTICE  "<5>"  /* normal but significant condition */
+#define SD_INFO    "<6>"  /* informational */
+#define SD_DEBUG   "<7>"  /* debug-level messages */
+
+/* The first passed file descriptor is fd 3 */
+#define SD_LISTEN_FDS_START 3
+
+/*
+  Returns how many file descriptors have been passed, or a negative
+  errno code on failure. Optionally, removes the $LISTEN_FDS and
+  $LISTEN_PID file descriptors from the environment (recommended, but
+  problematic in threaded environments). If r is the return value of
+  this function you'll find the file descriptors passed as fds
+  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
+  errno style error code on failure. This function call ensures that
+  the FD_CLOEXEC flag is set for the passed file descriptors, to make
+  sure they are not passed on to child processes. If FD_CLOEXEC shall
+  not be set, the caller needs to unset it after this call for all file
+  descriptors that are used.
+
+  See sd_listen_fds(3) for more information.
+*/
+int sd_listen_fds(int unset_environment);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a FIFO in the file system stored under the
+  specified path, 0 otherwise. If path is NULL a path name check will
+  not be done and the call only verifies if the file descriptor
+  refers to a FIFO. Returns a negative errno style error code on
+  failure.
+
+  See sd_is_fifo(3) for more information.
+*/
+int sd_is_fifo(int fd, const char *path);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a special character device on the file
+  system stored under the specified path, 0 otherwise.
+  If path is NULL a path name check will not be done and the call
+  only verifies if the file descriptor refers to a special character.
+  Returns a negative errno style error code on failure.
+
+  See sd_is_special(3) for more information.
+*/
+int sd_is_special(int fd, const char *path);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a socket of the specified family (AF_INET,
+  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
+  family is 0 a socket family check will not be done. If type is 0 a
+  socket type check will not be done and the call only verifies if
+  the file descriptor refers to a socket. If listening is > 0 it is
+  verified that the socket is in listening mode. (i.e. listen() has
+  been called) If listening is == 0 it is verified that the socket is
+  not in listening mode. If listening is < 0 no listening mode check
+  is done. Returns a negative errno style error code on failure.
+
+  See sd_is_socket(3) for more information.
+*/
+int sd_is_socket(int fd, int family, int type, int listening);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an Internet socket, of the specified family
+  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
+  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
+  check is not done. If type is 0 a socket type check will not be
+  done. If port is 0 a socket port check will not be done. The
+  listening flag is used the same way as in sd_is_socket(). Returns a
+  negative errno style error code on failure.
+
+  See sd_is_socket_inet(3) for more information.
+*/
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an AF_UNIX socket of the specified type
+  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
+  a socket type check will not be done. If path is NULL a socket path
+  check will not be done. For normal AF_UNIX sockets set length to
+  0. For abstract namespace sockets set length to the length of the
+  socket name (including the initial 0 byte), and pass the full
+  socket path in path (including the initial 0 byte). The listening
+  flag is used the same way as in sd_is_socket(). Returns a negative
+  errno style error code on failure.
+
+  See sd_is_socket_unix(3) for more information.
+*/
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a POSIX Message Queue of the specified name,
+  0 otherwise. If path is NULL a message queue name check is not
+  done. Returns a negative errno style error code on failure.
+*/
+int sd_is_mq(int fd, const char *path);
+
+/*
+  Informs systemd about changed daemon state. This takes a number of
+  newline separated environment-style variable assignments in a
+  string. The following variables are known:
+
+     READY=1      Tells systemd that daemon startup is finished (only
+                  relevant for services of Type=notify). The passed
+                  argument is a boolean "1" or "0". Since there is
+                  little value in signaling non-readiness the only
+                  value daemons should send is "READY=1".
+
+     STATUS=...   Passes a single-line status string back to systemd
+                  that describes the daemon state. This is free-from
+                  and can be used for various purposes: general state
+                  feedback, fsck-like programs could pass completion
+                  percentages and failing programs could pass a human
+                  readable error message. Example: "STATUS=Completed
+                  66% of file system check..."
+
+     ERRNO=...    If a daemon fails, the errno-style error code,
+                  formatted as string. Example: "ERRNO=2" for ENOENT.
+
+     BUSERROR=... If a daemon fails, the D-Bus error-style error
+                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
+
+     MAINPID=...  The main pid of a daemon, in case systemd did not
+                  fork off the process itself. Example: "MAINPID=4711"
+
+     WATCHDOG=1   Tells systemd to update the watchdog timestamp.
+                  Services using this feature should do this in
+                  regular intervals. A watchdog framework can use the
+                  timestamps to detect failed services.
+
+  Daemons can choose to send additional variables. However, it is
+  recommended to prefix variable names not listed above with X_.
+
+  Returns a negative errno-style error code on failure. Returns > 0
+  if systemd could be notified, 0 if it couldn't possibly because
+  systemd is not running.
+
+  Example: When a daemon finished starting up, it could issue this
+  call to notify systemd about it:
+
+     sd_notify(0, "READY=1");
+
+  See sd_notifyf() for more complete examples.
+
+  See sd_notify(3) for more information.
+*/
+int sd_notify(int unset_environment, const char *state);
+
+/*
+  Similar to sd_notify() but takes a format string.
+
+  Example 1: A daemon could send the following after initialization:
+
+     sd_notifyf(0, "READY=1\n"
+                   "STATUS=Processing requests...\n"
+                   "MAINPID=%lu",
+                   (unsigned long) getpid());
+
+  Example 2: A daemon could send the following shortly before
+  exiting, on failure:
+
+     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
+                   "ERRNO=%i",
+                   strerror(errno),
+                   errno);
+
+  See sd_notifyf(3) for more information.
+*/
+int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
+
+/*
+  Returns > 0 if the system was booted with systemd. Returns < 0 on
+  error. Returns 0 if the system was not booted with systemd. Note
+  that all of the functions above handle non-systemd boots just
+  fine. You should NOT protect them with a call to this function. Also
+  note that this function checks whether the system, not the user
+  session is controlled by systemd. However the functions above work
+  for both user and system services.
+
+  See sd_booted(3) for more information.
+*/
+int sd_booted(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/misc-utils/uuidd.8 b/misc-utils/uuidd.8
index e3ccf6f..90763f7 100644
--- a/misc-utils/uuidd.8
+++ b/misc-utils/uuidd.8
@@ -42,6 +42,12 @@ Do not create pid file.
 .BR \-F , " \-\-no-fork "
 Do not daemonize using double-fork.
 .TP
+.BR \-S , " \-\-socket-activation "
+Do not create the socket and instead expect it to be provided by the calling
+process.  Implies --no-fork and --no-pid.  As of this writing, this option is
+supposed to be used only with systemd.  This option must be enabled with a configure
+option.
+.TP
 .B \-q
 Suppress some failure messages.
 .TP
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 0ea6288..c6ec208 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -35,8 +35,12 @@ extern int optind;
 #include "uuidd.h"
 #include "writeall.h"
 #include "c.h"
-
 #include "closestream.h"
+
+#ifdef USE_SOCKET_ACTIVATION
+#include "sd-daemon.h"
+#endif
+
 #include "nls.h"
 
 #ifdef __GNUC__
@@ -58,19 +62,20 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 	      _(" %s [options]\n"), program_invocation_short_name);
 
 	fputs(_("\nOptions:\n"), out);
-	fputs(_(" -p, --pid <path>    path to pid file\n"
-		" -s, --socket <path> path to socket\n"
-		" -T, --timeout <sec> specify inactivity timeout\n"
-		" -k, --kill          kill running daemon\n"
-		" -r, --random        test random-based generation\n"
-		" -t, --time          test time-based generation\n"
-		" -n, --uuids <num>   request number of uuids\n"
-		" -P, --no-pid        do not create pid file\n"
-		" -F, --no-fork       do not daemonize using double-fork\n"
-		" -d, --debug         run in debugging mode\n"
-		" -q, --quiet         turn on quiet mode\n"
-		" -V, --version       output version information and exit\n"
-		" -h, --help          display this help and exit\n\n"), out);
+	fputs(_(" -p, --pid <path>        path to pid file\n"
+		" -s, --socket <path>     path to socket\n"
+		" -T, --timeout <sec>     specify inactivity timeout\n"
+		" -k, --kill              kill running daemon\n"
+		" -r, --random            test random-based generation\n"
+		" -t, --time              test time-based generation\n"
+		" -n, --uuids <num>       request number of uuids\n"
+		" -P, --no-pid            do not create pid file\n"
+		" -F, --no-fork           do not daemonize using double-fork\n"
+		" -S, --socket-activation do not create listening socket\n"
+		" -d, --debug             run in debugging mode\n"
+		" -q, --quiet             turn on quiet mode\n"
+		" -V, --version           output version information and exit\n"
+		" -h, --help              display this help and exit\n\n"), out);
 
 	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
@@ -302,7 +307,8 @@ static int create_socket(const char *socket_path, int will_fork, int quiet)
 }
 
 static void server_loop(const char *socket_path, const char *pidfile_path,
-			int debug, int timeout, int quiet, int no_fork)
+			int debug, int timeout, int quiet, int no_fork,
+			int no_sock)
 {
 	struct sockaddr_un	from_addr;
 	socklen_t		fromlen;
@@ -310,48 +316,68 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	uuid_t			uu;
 	char			reply_buf[1024], *cp;
 	char			op, str[UUID_STR_LEN];
-	int			i, s, ns, len, num;
+	int			i, ns, len, num;
+	int			s = 0;
 	int			fd_pidfile = -1;
 	int			ret;
 
-	signal(SIGALRM, terminate_intr);
-	alarm(30);
+#ifdef USE_SOCKET_ACTIVATION
+	if (!no_sock)	/* no_sock implies no_fork and no_pid */
+#endif
+	{
 
-	if (pidfile_path)
-		fd_pidfile = create_pidfile(pidfile_path, quiet);
+		signal(SIGALRM, terminate_intr);
+		alarm(30);
+		if (pidfile_path)
+			fd_pidfile = create_pidfile(pidfile_path, quiet);
 
-	ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf, sizeof(reply_buf), 0, NULL);
-	if (ret > 0) {
-		if (!quiet)
-			printf(_("uuidd daemon already running at pid %s\n"),
-			       reply_buf);
-		exit(EXIT_FAILURE);
-	}
-	alarm(0);
+		ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
+				  sizeof(reply_buf), 0, NULL);
+		if (ret > 0) {
+			if (!quiet)
+				printf(_("uuidd daemon already running at pid %s\n"),
+				       reply_buf);
+			exit(EXIT_FAILURE);
+		}
+		alarm(0);
+
+		s = create_socket(socket_path, (!debug || !no_fork), quiet);
+		if (listen(s, SOMAXCONN) < 0) {
+			if (!quiet)
+				fprintf(stderr, _("Couldn't listen on unix "
+						  "socket %s: %m\n"), socket_path);
+			exit(EXIT_FAILURE);
+		}
+
+		if (!debug && !no_fork)
+			create_daemon();
+
+		if (pidfile_path) {
+			sprintf(reply_buf, "%8d\n", getpid());
+			ignore_result( ftruncate(fd_pidfile, 0) );
+			write_all(fd_pidfile, reply_buf, strlen(reply_buf));
+			if (fd_pidfile > 1)
+				close(fd_pidfile); /* Unlock the pid file */
+		}
 
-	s = create_socket(socket_path, (!debug || !no_fork), quiet);
-	if (listen(s, SOMAXCONN) < 0) {
-		if (!quiet)
-			fprintf(stderr, _("Couldn't listen on unix "
-					  "socket %s: %m\n"), socket_path);
-		exit(EXIT_FAILURE);
 	}
 
-	if (!debug && !no_fork)
-		create_daemon();
 	signal(SIGHUP, terminate_intr);
 	signal(SIGINT, terminate_intr);
 	signal(SIGTERM, terminate_intr);
 	signal(SIGALRM, terminate_intr);
 	signal(SIGPIPE, SIG_IGN);
 
-	if (pidfile_path) {
-		sprintf(reply_buf, "%8d\n", getpid());
-		ignore_result( ftruncate(fd_pidfile, 0) );
-		write_all(fd_pidfile, reply_buf, strlen(reply_buf));
-		if (fd_pidfile > 1)
-			close(fd_pidfile); /* Unlock the pid file */
+#ifdef USE_SOCKET_ACTIVATION
+	if (no_sock) {
+		if (sd_listen_fds(0) != 1) {
+			fprintf(stderr, _("No or too many file descriptors received.\n"));
+			exit(EXIT_FAILURE);
+		}
+
+		s = SD_LISTEN_FDS_START + 0;
 	}
+#endif
 
 	while (1) {
 		fromlen = sizeof(from_addr);
@@ -482,6 +508,7 @@ int main(int argc, char **argv)
 	int		debug = 0, do_type = 0, do_kill = 0, num = 0;
 	int		timeout = 0, quiet = 0, drop_privs = 0;
 	int		no_pid = 0, no_fork = 0;
+	int		no_sock = 0, s_flag = 0;
 
 	static const struct option longopts[] = {
 		{"pid", required_argument, NULL, 'p'},
@@ -493,6 +520,7 @@ int main(int argc, char **argv)
 		{"uuids", required_argument, NULL, 'n'},
 		{"no-pid", no_argument, NULL, 'P'},
 		{"no-fork", no_argument, NULL, 'F'},
+		{"socket-activation", no_argument, NULL, 'S'},
 		{"debug", no_argument, NULL, 'd'},
 		{"quiet", no_argument, NULL, 'q'},
 		{"version", no_argument, NULL, 'V'},
@@ -506,7 +534,7 @@ int main(int argc, char **argv)
 	atexit(close_stdout);
 
 	while ((c =
-		getopt_long(argc, argv, "p:s:T:krtn:PFdqVh", longopts,
+		getopt_long(argc, argv, "p:s:T:krtn:PFSdqVh", longopts,
 			    NULL)) != -1) {
 		switch (c) {
 		case 'd':
@@ -536,6 +564,18 @@ int main(int argc, char **argv)
 			no_fork = 1;
 			drop_privs = 1;
 			break;
+		case 'S':
+#ifdef USE_SOCKET_ACTIVATION
+			no_sock = 1;
+			drop_privs = 1;
+			no_fork = 1;
+			no_pid = 1;
+#else
+			fprintf(stderr,
+				_("uuidd has been built without support for socket activation.\n"));
+			return EXIT_FAILURE;
+#endif
+			break;
 		case 'q':
 			quiet++;
 			break;
@@ -545,6 +585,7 @@ int main(int argc, char **argv)
 			break;
 		case 's':
 			socket_path = optarg;
+			s_flag = 1;
 			drop_privs = 1;
 			break;
 		case 't':
@@ -579,6 +620,10 @@ int main(int argc, char **argv)
 	else if (pidfile_path_param)
 		pidfile_path = pidfile_path_param;
 
+	/* custom socket path and socket-activation make no sense */
+	if (s_flag && no_sock && !quiet)
+		fprintf(stderr, _("Both --socket-activation and --socket specified. "
+				  "Ignoring --socket\n"));
 
 	uid = getuid();
 	if (uid && drop_privs) {
@@ -661,6 +706,7 @@ int main(int argc, char **argv)
 		return EXIT_SUCCESS;
 	}
 
-	server_loop(socket_path, pidfile_path, debug, timeout, quiet, no_fork);
+	server_loop(socket_path, pidfile_path, debug, timeout, quiet, no_fork,
+		    no_sock);
 	return EXIT_SUCCESS;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/15] uuidd: print all debugging information to stderr
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (7 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 08/15] uuidd: implement --socket-activation option Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 10/15] uuidd: do not drop privileges Petr Uzel
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |   29 +++++++++++++++--------------
 1 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index c6ec208..fafc8d1 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -335,7 +335,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 				  sizeof(reply_buf), 0, NULL);
 		if (ret > 0) {
 			if (!quiet)
-				printf(_("uuidd daemon already running at pid %s\n"),
+				fprintf(stderr,
+					_("uuidd daemon already running at pid %s\n"),
 				       reply_buf);
 			exit(EXIT_FAILURE);
 		}
@@ -396,7 +397,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			if (len < 0)
 				perror("read");
 			else
-				printf(_("Error reading from client, "
+				fprintf(stderr, _("Error reading from client, "
 					 "len = %d\n"), len);
 			goto shutdown_socket;
 		}
@@ -405,10 +406,10 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			if (read_all(ns, (char *) &num, sizeof(num)) != 4)
 				goto shutdown_socket;
 			if (debug)
-				printf(_("operation %d, incoming num = %d\n"),
+				fprintf(stderr, _("operation %d, incoming num = %d\n"),
 				       op, num);
 		} else if (debug)
-			printf(_("operation %d\n"), op);
+			fprintf(stderr, _("operation %d\n"), op);
 
 		switch (op) {
 		case UUIDD_OP_GETPID:
@@ -424,7 +425,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			__uuid_generate_time(uu, &num);
 			if (debug) {
 				uuid_unparse(uu, str);
-				printf(_("Generated time UUID: %s\n"), str);
+				fprintf(stderr, _("Generated time UUID: %s\n"), str);
 			}
 			memcpy(reply_buf, uu, sizeof(uu));
 			reply_len = sizeof(uu);
@@ -434,7 +435,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			__uuid_generate_random(uu, &num);
 			if (debug) {
 				uuid_unparse(uu, str);
-				printf(_("Generated random UUID: %s\n"), str);
+				fprintf(stderr, _("Generated random UUID: %s\n"), str);
 			}
 			memcpy(reply_buf, uu, sizeof(uu));
 			reply_len = sizeof(uu);
@@ -443,10 +444,10 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			__uuid_generate_time(uu, &num);
 			if (debug) {
 				uuid_unparse(uu, str);
-				printf(P_("Generated time UUID %s "
-					  "and %d following\n",
-					  "Generated time UUID %s "
-					  "and %d following\n", num - 1),
+				fprintf(stderr, P_("Generated time UUID %s "
+						   "and %d following\n",
+						   "Generated time UUID %s "
+						   "and %d following\n", num - 1),
 				       str, num - 1);
 			}
 			memcpy(reply_buf, uu, sizeof(uu));
@@ -464,13 +465,13 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			__uuid_generate_random((unsigned char *) reply_buf +
 					      sizeof(num), &num);
 			if (debug) {
-				printf(P_("Generated %d UUID:\n",
-					  "Generated %d UUIDs:\n", num), num);
+				fprintf(stderr, P_("Generated %d UUID:\n",
+						   "Generated %d UUIDs:\n", num), num);
 				for (i = 0, cp = reply_buf + sizeof(num);
 				     i < num;
 				     i++, cp += UUID_LEN) {
 					uuid_unparse((unsigned char *)cp, str);
-					printf("\t%s\n", str);
+					fprintf(stderr, "\t%s\n", str);
 				}
 			}
 			reply_len = (num * UUID_LEN) + sizeof(num);
@@ -478,7 +479,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			break;
 		default:
 			if (debug)
-				printf(_("Invalid operation %d\n"), op);
+				fprintf(stderr, _("Invalid operation %d\n"), op);
 			goto shutdown_socket;
 		}
 		write_all(ns, (char *) &reply_len, sizeof(reply_len));
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/15] uuidd: do not drop privileges
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (8 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 09/15] uuidd: print all debugging information to stderr Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 11/15] libuuid: use EXIT_FAILURE Petr Uzel
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

libuuid can (for now) spawn uuidd on-demand. To support this scenario,
uuidd should be installed setuid/setgid to have access to
/var/lib/libuuid/clock.txt. Therefore, dropping the privileges is
not functional, so removing this ability.

Moreover, the ability to spawn uuidd on-demand will be removed anyway.

References: http://www.spinics.net/lists/util-linux-ng/msg05934.html

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |   32 +-------------------------------
 1 files changed, 1 insertions(+), 31 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index fafc8d1..684e494 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -503,11 +503,9 @@ int main(int argc, char **argv)
 	char		buf[1024], *cp;
 	char		str[UUID_STR_LEN], *tmp;
 	uuid_t		uu;
-	uid_t		uid;
-	gid_t		gid;
 	int		i, c, ret;
 	int		debug = 0, do_type = 0, do_kill = 0, num = 0;
-	int		timeout = 0, quiet = 0, drop_privs = 0;
+	int		timeout = 0, quiet = 0;
 	int		no_pid = 0, no_fork = 0;
 	int		no_sock = 0, s_flag = 0;
 
@@ -540,11 +538,9 @@ int main(int argc, char **argv)
 		switch (c) {
 		case 'd':
 			debug++;
-			drop_privs = 1;
 			break;
 		case 'k':
 			do_kill++;
-			drop_privs = 1;
 			break;
 		case 'n':
 			num = strtol(optarg, &tmp, 0);
@@ -555,20 +551,16 @@ int main(int argc, char **argv)
 			break;
 		case 'p':
 			pidfile_path_param = optarg;
-			drop_privs = 1;
 			break;
 		case 'P':
 			no_pid = 1;
-			drop_privs = 1;
 			break;
 		case 'F':
 			no_fork = 1;
-			drop_privs = 1;
 			break;
 		case 'S':
 #ifdef USE_SOCKET_ACTIVATION
 			no_sock = 1;
-			drop_privs = 1;
 			no_fork = 1;
 			no_pid = 1;
 #else
@@ -582,16 +574,13 @@ int main(int argc, char **argv)
 			break;
 		case 'r':
 			do_type = UUIDD_OP_RANDOM_UUID;
-			drop_privs = 1;
 			break;
 		case 's':
 			socket_path = optarg;
 			s_flag = 1;
-			drop_privs = 1;
 			break;
 		case 't':
 			do_type = UUIDD_OP_TIME_UUID;
-			drop_privs = 1;
 			break;
 		case 'T':
 			timeout = strtol(optarg, &tmp, 0);
@@ -626,25 +615,6 @@ int main(int argc, char **argv)
 		fprintf(stderr, _("Both --socket-activation and --socket specified. "
 				  "Ignoring --socket\n"));
 
-	uid = getuid();
-	if (uid && drop_privs) {
-		gid = getgid();
-#ifdef HAVE_SETRESGID
-		if (setresgid(gid, gid, gid) < 0)
-			err(EXIT_FAILURE, "setresgid");
-#else
-		if (setregid(gid, gid) < 0)
-			err(EXIT_FAILURE, "setregid");
-#endif
-
-#ifdef HAVE_SETRESUID
-		if (setresuid(uid, uid, uid) < 0)
-			err(EXIT_FAILURE, "setresuid");
-#else
-		if (setreuid(uid, uid) < 0)
-			err(EXIT_FAILURE, "setreuid");
-#endif
-	}
 	if (num && do_type) {
 		ret = call_daemon(socket_path, do_type + 2, buf,
 				  sizeof(buf), &num, &err_context);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/15] libuuid: use EXIT_FAILURE
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (9 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 10/15] uuidd: do not drop privileges Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 12/15] uuidd: add systemd unit files Petr Uzel
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 libuuid/src/gen_uuid.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
index caa240e..8c102b1 100644
--- a/libuuid/src/gen_uuid.c
+++ b/libuuid/src/gen_uuid.c
@@ -416,7 +416,7 @@ static int get_uuid_via_daemon(int op, uuid_t out, int *num)
 				close_all_fds();
 				execl(uuidd_path, "uuidd", "-qT", "300",
 				      (char *) NULL);
-				exit(1);
+				exit(EXIT_FAILURE);
 			}
 			(void) waitpid(pid, 0, 0);
 			if (connect(s, (const struct sockaddr *) &srv_addr,
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 12/15] uuidd: add systemd unit files
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (10 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 11/15] libuuid: use EXIT_FAILURE Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:01 ` [PATCH 13/15] libuuid: don't exec uuidd Petr Uzel
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Add systemd unit files which use the socket activation mechanism
of systemd. The uuidd deamon is started upon first request on the
socket and quits after 1 minute of inactivity.

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 Makefile.am                 |    3 ++-
 configure.ac                |   11 +++++++++++
 misc-utils/.gitignore       |    1 +
 misc-utils/Makefile.am      |   11 +++++++++--
 misc-utils/uuidd.service.in |    9 +++++++++
 misc-utils/uuidd.socket     |    8 ++++++++
 6 files changed, 40 insertions(+), 3 deletions(-)
 create mode 100644 misc-utils/uuidd.service.in
 create mode 100644 misc-utils/uuidd.socket

diff --git a/Makefile.am b/Makefile.am
index 6fec32d..12e1103 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -89,7 +89,8 @@ checkxalloc:
 
 ENABLE_ALL = --enable-static-programs --enable-most-builds
 DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --disable-use-tty-group \
-			    --disable-silent-rules $(ENABLE_ALL)
+			    --disable-silent-rules $(ENABLE_ALL) \
+			    --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 
 
 BUILT_SOURCES = .version
diff --git a/configure.ac b/configure.ac
index f5f3a2e..d254349 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1134,6 +1134,16 @@ if test "x$enable_socket_activation" = xyes; then
   AC_DEFINE(USE_SOCKET_ACTIVATION, 1, [Should uuidd support socket activation?])
 fi
 
+AC_ARG_WITH([systemdsystemunitdir],
+  AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [directory for systemd service files]),
+  [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+
+if test "x$with_systemdsystemunitdir" != "xno"; then
+  AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+
+AM_CONDITIONAL(WITH_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != "xno" ])
+
 
 AC_ARG_ENABLE([login-stat-mail],
   AS_HELP_STRING([--enable-login-stat-mail], [let login stat() the mailbox]),
@@ -1257,6 +1267,7 @@ libuuid/uuid.pc
 login-utils/Makefile
 man/ru/Makefile
 misc-utils/Makefile
+misc-utils/uuidd.service
 mount/Makefile
 partx/Makefile
 po/Makefile.in
diff --git a/misc-utils/.gitignore b/misc-utils/.gitignore
index 927af23..3fe5567 100644
--- a/misc-utils/.gitignore
+++ b/misc-utils/.gitignore
@@ -18,3 +18,4 @@ wipefs
 findmnt
 lsblk
 lslocks
+uuidd.service
diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am
index 47a639b..9dd3583 100644
--- a/misc-utils/Makefile.am
+++ b/misc-utils/Makefile.am
@@ -1,7 +1,5 @@
 include $(top_srcdir)/config/include-Makefile.am
 
-EXTRA_DIST = uuidd.rc
-
 bin_PROGRAMS =
 sbin_PROGRAMS =
 usrsbin_exec_PROGRAMS =
@@ -89,8 +87,17 @@ if USE_SOCKET_ACTIVATION
 uuidd_SOURCES += sd-daemon.c
 uuidd_LDADD += -lrt
 endif
+if WITH_SYSTEMD
+systemdsystemunit_DATA = \
+	uuidd.service \
+	uuidd.socket
+endif
 endif
 
+EXTRA_DIST = uuidd.rc uuidd.service.in uuidd.socket
+CLEANFILES += uuidd.service
+
+
 if BUILD_LIBBLKID
 sbin_PROGRAMS += blkid findfs wipefs
 dist_man_MANS += blkid.8 findfs.8 wipefs.8
diff --git a/misc-utils/uuidd.service.in b/misc-utils/uuidd.service.in
new file mode 100644
index 0000000..750fc31
--- /dev/null
+++ b/misc-utils/uuidd.service.in
@@ -0,0 +1,9 @@
+[Unit]
+Description=Daemon for generating UUIDs
+Requires=uuidd.socket
+
+[Service]
+ExecStart=@sbindir@/uuidd -S -T 60
+Restart=no
+User=uuidd
+Group=uuidd
diff --git a/misc-utils/uuidd.socket b/misc-utils/uuidd.socket
new file mode 100644
index 0000000..4eba789
--- /dev/null
+++ b/misc-utils/uuidd.socket
@@ -0,0 +1,8 @@
+[Unit]
+Description=UUID daemon activation socket
+
+[Socket]
+ListenStream=/var/run/uuidd/request
+
+[Install]
+WantedBy=sockets.target
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 13/15] libuuid: don't exec uuidd
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (11 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 12/15] uuidd: add systemd unit files Petr Uzel
@ 2012-05-03 19:01 ` Petr Uzel
  2012-05-03 19:02 ` [PATCH 14/15] uuidd: introduce uuidd_cxt to pass arguments to server loop Petr Uzel
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:01 UTC (permalink / raw)
  To: util-linux

Executing the daemon from the shared library is not quite elegant
solution. Drop this functionality and require uuidd (should it be
needed) to be started from the initscript or by socket-activation.

References: http://www.spinics.net/lists/util-linux-ng/msg05967.html

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 libuuid/src/Makefile.am |    1 -
 libuuid/src/gen_uuid.c  |   48 ++--------------------------------------------
 2 files changed, 3 insertions(+), 46 deletions(-)

diff --git a/libuuid/src/Makefile.am b/libuuid/src/Makefile.am
index 1df282e..8e87210 100644
--- a/libuuid/src/Makefile.am
+++ b/libuuid/src/Makefile.am
@@ -26,7 +26,6 @@ libuuid_la_SOURCES = \
 	uuidP.h \
 	uuid_time.c \
 	$(uuidinc_HEADERS) \
-	$(top_srcdir)/lib/fileutils.c \
 	$(top_srcdir)/lib/randutils.c
 
 libuuid_la_DEPENDENCIES = uuid.sym
diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
index 8c102b1..8ff4129 100644
--- a/libuuid/src/gen_uuid.c
+++ b/libuuid/src/gen_uuid.c
@@ -58,7 +58,6 @@
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
-#include <sys/wait.h>
 #include <sys/stat.h>
 #ifdef HAVE_SYS_FILE_H
 #include <sys/file.h>
@@ -87,14 +86,10 @@
 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
 #include <sys/syscall.h>
 #endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
 
 #include "uuidP.h"
 #include "uuidd.h"
 #include "randutils.h"
-#include "fileutils.h"
 
 #ifdef HAVE_TLS
 #define THREAD_LOCAL static __thread
@@ -365,20 +360,6 @@ static ssize_t read_all(int fd, char *buf, size_t count)
 }
 
 /*
- * Close all file descriptors
- */
-static void close_all_fds(void)
-{
-	int i, max = get_fd_tabsize();
-
-	for (i=0; i < max; i++) {
-		close(i);
-		if (i <= 2)
-			open("/dev/null", O_RDWR);
-	}
-}
-
-/*
  * Try using the uuidd daemon to generate the UUID
  *
  * Returns 0 on success, non-zero on failure.
@@ -391,11 +372,6 @@ static int get_uuid_via_daemon(int op, uuid_t out, int *num)
 	ssize_t ret;
 	int32_t reply_len = 0, expected = 16;
 	struct sockaddr_un srv_addr;
-	struct stat st;
-	pid_t pid;
-	static const char *uuidd_path = UUIDD_PATH;
-	static int access_ret = -2;
-	static int start_attempts = 0;
 
 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
 		return -1;
@@ -404,27 +380,9 @@ static int get_uuid_via_daemon(int op, uuid_t out, int *num)
 	strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
 
 	if (connect(s, (const struct sockaddr *) &srv_addr,
-		    sizeof(struct sockaddr_un)) < 0) {
-		if (access_ret == -2)
-			access_ret = access(uuidd_path, X_OK);
-		if (access_ret == 0)
-			access_ret = stat(uuidd_path, &st);
-		if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0)
-			access_ret = access(UUIDD_DIR, W_OK);
-		if (access_ret == 0 && start_attempts++ < 5) {
-			if ((pid = fork()) == 0) {
-				close_all_fds();
-				execl(uuidd_path, "uuidd", "-qT", "300",
-				      (char *) NULL);
-				exit(EXIT_FAILURE);
-			}
-			(void) waitpid(pid, 0, 0);
-			if (connect(s, (const struct sockaddr *) &srv_addr,
-				    sizeof(struct sockaddr_un)) < 0)
-				goto fail;
-		} else
-			goto fail;
-	}
+		    sizeof(struct sockaddr_un)) < 0)
+		goto fail;
+
 	op_buf[0] = op;
 	op_len = 1;
 	if (op == UUIDD_OP_BULK_TIME_UUID) {
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 14/15] uuidd: introduce uuidd_cxt to pass arguments to server loop
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (12 preceding siblings ...)
  2012-05-03 19:01 ` [PATCH 13/15] libuuid: don't exec uuidd Petr Uzel
@ 2012-05-03 19:02 ` Petr Uzel
  2012-05-03 19:02 ` [PATCH 15/15] libuuid: avoid double open and leaking descriptor Petr Uzel
  2012-05-04 14:25 ` [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Karel Zak
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:02 UTC (permalink / raw)
  To: util-linux


Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 misc-utils/uuidd.c |   56 +++++++++++++++++++++++++++++++++------------------
 1 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index 684e494..d20526e 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -55,6 +55,15 @@ extern int optind;
 /* length of binary representation of UUID */
 #define UUID_LEN	(sizeof(uuid_t))
 
+/* server loop control structure */
+struct uuidd_cxt_t {
+	int	timeout;
+	unsigned int	debug: 1,
+			quiet: 1,
+			no_fork: 1,
+			no_sock: 1;
+};
+
 static void __attribute__ ((__noreturn__)) usage(FILE * out)
 {
 	fputs(_("\nUsage:\n"), out);
@@ -307,8 +316,7 @@ static int create_socket(const char *socket_path, int will_fork, int quiet)
 }
 
 static void server_loop(const char *socket_path, const char *pidfile_path,
-			int debug, int timeout, int quiet, int no_fork,
-			int no_sock)
+			const struct uuidd_cxt_t *uuidd_cxt)
 {
 	struct sockaddr_un	from_addr;
 	socklen_t		fromlen;
@@ -322,19 +330,19 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	int			ret;
 
 #ifdef USE_SOCKET_ACTIVATION
-	if (!no_sock)	/* no_sock implies no_fork and no_pid */
+	if (!uuidd_cxt->no_sock)	/* no_sock implies no_fork and no_pid */
 #endif
 	{
 
 		signal(SIGALRM, terminate_intr);
 		alarm(30);
 		if (pidfile_path)
-			fd_pidfile = create_pidfile(pidfile_path, quiet);
+			fd_pidfile = create_pidfile(pidfile_path, uuidd_cxt->quiet);
 
 		ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
 				  sizeof(reply_buf), 0, NULL);
 		if (ret > 0) {
-			if (!quiet)
+			if (!uuidd_cxt->quiet)
 				fprintf(stderr,
 					_("uuidd daemon already running at pid %s\n"),
 				       reply_buf);
@@ -342,15 +350,17 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		}
 		alarm(0);
 
-		s = create_socket(socket_path, (!debug || !no_fork), quiet);
+		s = create_socket(socket_path,
+				  (!uuidd_cxt->debug || !uuidd_cxt->no_fork),
+				  uuidd_cxt->quiet);
 		if (listen(s, SOMAXCONN) < 0) {
-			if (!quiet)
+			if (!uuidd_cxt->quiet)
 				fprintf(stderr, _("Couldn't listen on unix "
 						  "socket %s: %m\n"), socket_path);
 			exit(EXIT_FAILURE);
 		}
 
-		if (!debug && !no_fork)
+		if (!uuidd_cxt->debug && !uuidd_cxt->no_fork)
 			create_daemon();
 
 		if (pidfile_path) {
@@ -370,7 +380,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	signal(SIGPIPE, SIG_IGN);
 
 #ifdef USE_SOCKET_ACTIVATION
-	if (no_sock) {
+	if (uuidd_cxt->no_sock) {
 		if (sd_listen_fds(0) != 1) {
 			fprintf(stderr, _("No or too many file descriptors received.\n"));
 			exit(EXIT_FAILURE);
@@ -382,8 +392,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 
 	while (1) {
 		fromlen = sizeof(from_addr);
-		if (timeout > 0)
-			alarm(timeout);
+		if (uuidd_cxt->timeout > 0)
+			alarm(uuidd_cxt->timeout);
 		ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
 		alarm(0);
 		if (ns < 0) {
@@ -405,10 +415,10 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		    (op == UUIDD_OP_BULK_RANDOM_UUID)) {
 			if (read_all(ns, (char *) &num, sizeof(num)) != 4)
 				goto shutdown_socket;
-			if (debug)
+			if (uuidd_cxt->debug)
 				fprintf(stderr, _("operation %d, incoming num = %d\n"),
 				       op, num);
-		} else if (debug)
+		} else if (uuidd_cxt->debug)
 			fprintf(stderr, _("operation %d\n"), op);
 
 		switch (op) {
@@ -423,7 +433,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		case UUIDD_OP_TIME_UUID:
 			num = 1;
 			__uuid_generate_time(uu, &num);
-			if (debug) {
+			if (uuidd_cxt->debug) {
 				uuid_unparse(uu, str);
 				fprintf(stderr, _("Generated time UUID: %s\n"), str);
 			}
@@ -433,7 +443,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 		case UUIDD_OP_RANDOM_UUID:
 			num = 1;
 			__uuid_generate_random(uu, &num);
-			if (debug) {
+			if (uuidd_cxt->debug) {
 				uuid_unparse(uu, str);
 				fprintf(stderr, _("Generated random UUID: %s\n"), str);
 			}
@@ -442,7 +452,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			break;
 		case UUIDD_OP_BULK_TIME_UUID:
 			__uuid_generate_time(uu, &num);
-			if (debug) {
+			if (uuidd_cxt->debug) {
 				uuid_unparse(uu, str);
 				fprintf(stderr, P_("Generated time UUID %s "
 						   "and %d following\n",
@@ -464,7 +474,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 				num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
 			__uuid_generate_random((unsigned char *) reply_buf +
 					      sizeof(num), &num);
-			if (debug) {
+			if (uuidd_cxt->debug) {
 				fprintf(stderr, P_("Generated %d UUID:\n",
 						   "Generated %d UUIDs:\n", num), num);
 				for (i = 0, cp = reply_buf + sizeof(num);
@@ -478,7 +488,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			memcpy(reply_buf, &num, sizeof(num));
 			break;
 		default:
-			if (debug)
+			if (uuidd_cxt->debug)
 				fprintf(stderr, _("Invalid operation %d\n"), op);
 			goto shutdown_socket;
 		}
@@ -508,6 +518,7 @@ int main(int argc, char **argv)
 	int		timeout = 0, quiet = 0;
 	int		no_pid = 0, no_fork = 0;
 	int		no_sock = 0, s_flag = 0;
+	struct uuidd_cxt_t uuidd_cxt;
 
 	static const struct option longopts[] = {
 		{"pid", required_argument, NULL, 'p'},
@@ -677,7 +688,12 @@ int main(int argc, char **argv)
 		return EXIT_SUCCESS;
 	}
 
-	server_loop(socket_path, pidfile_path, debug, timeout, quiet, no_fork,
-		    no_sock);
+	uuidd_cxt.timeout = timeout;
+	uuidd_cxt.debug = debug;
+	uuidd_cxt.quiet = quiet;
+	uuidd_cxt.no_fork = no_fork;
+	uuidd_cxt.no_sock = no_sock;
+
+	server_loop(socket_path, pidfile_path, &uuidd_cxt);
 	return EXIT_SUCCESS;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 15/15] libuuid: avoid double open and leaking descriptor
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (13 preceding siblings ...)
  2012-05-03 19:02 ` [PATCH 14/15] uuidd: introduce uuidd_cxt to pass arguments to server loop Petr Uzel
@ 2012-05-03 19:02 ` Petr Uzel
  2012-05-04 14:25 ` [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Karel Zak
  15 siblings, 0 replies; 17+ messages in thread
From: Petr Uzel @ 2012-05-03 19:02 UTC (permalink / raw)
  To: util-linux

We are opening /dev/urandom twice in uuid_generate(): first to check if
the file is available and then later __uuid_generate_random() again to
actually get the random data. Moreover, descriptor from the first open
is leaking.

Fix by passign the descriptor down the stack and reusing it there.

References: http://marc.info/?l=util-linux-ng&m=133406051131131&w=2

Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 fdisk/fdiskdoslabel.c  |    2 +-
 include/randutils.h    |    2 +-
 lib/randutils.c        |    8 +++++---
 libuuid/src/gen_uuid.c |   17 ++++++++++-------
 libuuid/src/uuidd.h    |    2 +-
 misc-utils/uuidd.c     |    4 ++--
 6 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/fdisk/fdiskdoslabel.c b/fdisk/fdiskdoslabel.c
index 6a9a044..c6e4198 100644
--- a/fdisk/fdiskdoslabel.c
+++ b/fdisk/fdiskdoslabel.c
@@ -182,7 +182,7 @@ void create_doslabel(void)
 	unsigned int id;
 
 	/* random disk signature */
-	random_get_bytes(&id, sizeof(id));
+	random_get_bytes(&id, sizeof(id), -1);
 
 	fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id);
 
diff --git a/include/randutils.h b/include/randutils.h
index dec5e35..d5d00f4 100644
--- a/include/randutils.h
+++ b/include/randutils.h
@@ -7,6 +7,6 @@
 #endif
 
 extern int random_get_fd(void);
-extern void random_get_bytes(void *buf, size_t nbytes);
+extern void random_get_bytes(void *buf, size_t nbytes, int fd);
 
 #endif
diff --git a/lib/randutils.c b/lib/randutils.c
index b90c886..0513798 100644
--- a/lib/randutils.c
+++ b/lib/randutils.c
@@ -58,13 +58,15 @@ int random_get_fd(void)
  * Use /dev/urandom if possible, and if not,
  * use glibc pseudo-random functions.
  */
-void random_get_bytes(void *buf, size_t nbytes)
+void random_get_bytes(void *buf, size_t nbytes, int fd)
 {
 	size_t i, n = nbytes;
-	int fd = random_get_fd();
 	int lose_counter = 0;
 	unsigned char *cp = (unsigned char *) buf;
 
+	if (fd < 0)
+		fd = random_get_fd();
+
 	if (fd >= 0) {
 		while (n > 0) {
 			ssize_t x = read(fd, cp, n);
@@ -111,7 +113,7 @@ int main(int argc, char *argv[])
 
 	/* generate and print 10 random numbers */
 	for (i = 0; i < 10; i++) {
-		random_get_bytes(&v, sizeof(v));
+		random_get_bytes(&v, sizeof(v), -1);
 		printf("%d\n", v);
 	}
 
diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
index 8ff4129..76f1bbd 100644
--- a/libuuid/src/gen_uuid.c
+++ b/libuuid/src/gen_uuid.c
@@ -277,7 +277,7 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
 	}
 
 	if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
-		random_get_bytes(&clock_seq, sizeof(clock_seq));
+		random_get_bytes(&clock_seq, sizeof(clock_seq), -1);
 		clock_seq &= 0x3FFF;
 		gettimeofday(&last, 0);
 		last.tv_sec--;
@@ -434,7 +434,7 @@ int __uuid_generate_time(uuid_t out, int *num)
 
 	if (!has_init) {
 		if (get_node_id(node_id) <= 0) {
-			random_get_bytes(node_id, 6);
+			random_get_bytes(node_id, 6, -1);
 			/*
 			 * Set multicast bit, to prevent conflicts
 			 * with IEEE 802 addresses obtained from
@@ -520,7 +520,7 @@ int uuid_generate_time_safe(uuid_t out)
 }
 
 
-void __uuid_generate_random(uuid_t out, int *num)
+void __uuid_generate_random(uuid_t out, int *num, int fd)
 {
 	uuid_t	buf;
 	struct uuid uu;
@@ -532,7 +532,7 @@ void __uuid_generate_random(uuid_t out, int *num)
 		n = *num;
 
 	for (i = 0; i < n; i++) {
-		random_get_bytes(buf, sizeof(buf));
+		random_get_bytes(buf, sizeof(buf), fd);
 		uuid_unpack(buf, &uu);
 
 		uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
@@ -548,7 +548,7 @@ void uuid_generate_random(uuid_t out)
 	int	num = 1;
 	/* No real reason to use the daemon for random uuid's -- yet */
 
-	__uuid_generate_random(out, &num);
+	__uuid_generate_random(out, &num, -1);
 }
 
 
@@ -560,8 +560,11 @@ void uuid_generate_random(uuid_t out)
  */
 void uuid_generate(uuid_t out)
 {
-	if (random_get_fd() >= 0)
-		uuid_generate_random(out);
+	int	fd;
+	int	num = 1;
+
+	if ((fd = random_get_fd()) >= 0)
+		__uuid_generate_random(out, &num, fd);
 	else
 		uuid_generate_time(out);
 }
diff --git a/libuuid/src/uuidd.h b/libuuid/src/uuidd.h
index 27b79c2..2e19522 100644
--- a/libuuid/src/uuidd.h
+++ b/libuuid/src/uuidd.h
@@ -49,6 +49,6 @@
 #define UUIDD_MAX_OP			UUIDD_OP_BULK_RANDOM_UUID
 
 extern int __uuid_generate_time(uuid_t out, int *num);
-extern void __uuid_generate_random(uuid_t out, int *num);
+extern void __uuid_generate_random(uuid_t out, int *num, int fd);
 
 #endif /* _UUID_UUID_H */
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index d20526e..d3ed3eb 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -442,7 +442,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			break;
 		case UUIDD_OP_RANDOM_UUID:
 			num = 1;
-			__uuid_generate_random(uu, &num);
+			__uuid_generate_random(uu, &num, -1);
 			if (uuidd_cxt->debug) {
 				uuid_unparse(uu, str);
 				fprintf(stderr, _("Generated random UUID: %s\n"), str);
@@ -473,7 +473,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 			if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
 				num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
 			__uuid_generate_random((unsigned char *) reply_buf +
-					      sizeof(num), &num);
+					      sizeof(num), &num, -1);
 			if (uuidd_cxt->debug) {
 				fprintf(stderr, P_("Generated %d UUID:\n",
 						   "Generated %d UUIDs:\n", num), num);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/15] uuidd: refactoring & systemd support (take 2)
  2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
                   ` (14 preceding siblings ...)
  2012-05-03 19:02 ` [PATCH 15/15] libuuid: avoid double open and leaking descriptor Petr Uzel
@ 2012-05-04 14:25 ` Karel Zak
  15 siblings, 0 replies; 17+ messages in thread
From: Karel Zak @ 2012-05-04 14:25 UTC (permalink / raw)
  To: Petr Uzel; +Cc: util-linux

On Thu, May 03, 2012 at 09:01:46PM +0200, Petr Uzel wrote:
> Regarding the last patch in the series, it addresses issue described in
> http://marc.info/?l=util-linux-ng&m=133405763330121&w=2 in the way recomended
> by Karel. However, after implementing it, I'm wondering: wouldn't it be cleaner
> to just test if /dev/u?random exists and is readable in uuid_generate() instead
> of calling random_get_fd() and passing the fd down the stack?

 random_get_fd() does much more than only open the file

>  Makefile.am                 |    3 +-
>  configure.ac                |   23 ++
>  fdisk/fdiskdoslabel.c       |    2 +-
>  include/randutils.h         |    2 +-
>  lib/randutils.c             |    8 +-
>  libuuid/src/Makefile.am     |    1 -
>  libuuid/src/gen_uuid.c      |   65 +-----
>  libuuid/src/uuidd.h         |    2 +-
>  misc-utils/.gitignore       |    1 +
>  misc-utils/Makefile.am      |   17 ++-
>  misc-utils/sd-daemon.c      |  530 +++++++++++++++++++++++++++++++++++++++++++
>  misc-utils/sd-daemon.h      |  282 +++++++++++++++++++++++
>  misc-utils/uuidd.8          |   12 +
>  misc-utils/uuidd.c          |  313 +++++++++++++++++---------
>  misc-utils/uuidd.service.in |    9 +
>  misc-utils/uuidd.socket     |    8 +
>  16 files changed, 1109 insertions(+), 169 deletions(-)
>  create mode 100644 misc-utils/sd-daemon.c
>  create mode 100644 misc-utils/sd-daemon.h
>  create mode 100644 misc-utils/uuidd.service.in
>  create mode 100644 misc-utils/uuidd.socket

 Applied, thanks a lot!

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-05-04 14:25 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-03 19:01 [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Petr Uzel
2012-05-03 19:01 ` [PATCH 01/15] uuidd: use UUIDD_OP_GETPID instead of magic number Petr Uzel
2012-05-03 19:01 ` [PATCH 02/15] uuidd: remove useless initialization of cleanup_socket Petr Uzel
2012-05-03 19:01 ` [PATCH 03/15] uuidd: factor out pidfile creation into separate function Petr Uzel
2012-05-03 19:01 ` [PATCH 04/15] uuidd: implement --no-pid option Petr Uzel
2012-05-03 19:01 ` [PATCH 05/15] uuidd: use ignore_result helper Petr Uzel
2012-05-03 19:01 ` [PATCH 06/15] uuidd: implement --no-fork option Petr Uzel
2012-05-03 19:01 ` [PATCH 07/15] uuidd: factor out socket creation into separate function Petr Uzel
2012-05-03 19:01 ` [PATCH 08/15] uuidd: implement --socket-activation option Petr Uzel
2012-05-03 19:01 ` [PATCH 09/15] uuidd: print all debugging information to stderr Petr Uzel
2012-05-03 19:01 ` [PATCH 10/15] uuidd: do not drop privileges Petr Uzel
2012-05-03 19:01 ` [PATCH 11/15] libuuid: use EXIT_FAILURE Petr Uzel
2012-05-03 19:01 ` [PATCH 12/15] uuidd: add systemd unit files Petr Uzel
2012-05-03 19:01 ` [PATCH 13/15] libuuid: don't exec uuidd Petr Uzel
2012-05-03 19:02 ` [PATCH 14/15] uuidd: introduce uuidd_cxt to pass arguments to server loop Petr Uzel
2012-05-03 19:02 ` [PATCH 15/15] libuuid: avoid double open and leaking descriptor Petr Uzel
2012-05-04 14:25 ` [PATCH 00/15] uuidd: refactoring & systemd support (take 2) Karel Zak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox