From 16545cf5d5f51cb67c03923cbb9c75a024bdaca8 Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Sat, 23 Dec 2017 18:07:43 +0000 Subject: [PATCH] Introduce the daemonfd function. The daemonfd function is equivalent to the daemon(3) function expect that arguments are descriptors. For example dhclient(8) which is sandboxed is unable to open /dev/null to close stdio instead it's allows to fail daemon(3) function to close the descriptors and then do it explicit in code. Instead of such hacks we can use now daemonfd. This API can be also helpful to migrate system to platforms like CheriBSD. Reviewed by: brooks@, bcr@, jilles@ (earlier version) Differential Revision: https://reviews.freebsd.org/D13433 --- include/stdlib.h | 1 + lib/libc/gen/Symbol.map | 1 + lib/libc/gen/daemon.3 | 34 +++++++++++++++++++++++++++-- lib/libc/gen/daemon.c | 48 ++++++++++++++++++++++++++++++----------- 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 93c4bb50cd7..56bb1566d58 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -274,6 +274,7 @@ int cgetstr(char *, const char *, char **); int cgetustr(char *, const char *, char **); int daemon(int, int); +int daemonfd(int, int); char *devname(__dev_t, __mode_t); char *devname_r(__dev_t, __mode_t, char *, int); char *fdevname(int); diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index d11815c05fa..44fb85a4fab 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -394,6 +394,7 @@ FBSD_1.4 { FBSD_1.5 { alphasort; basename; + daemonfd; devname; devname_r; dirname; diff --git a/lib/libc/gen/daemon.3 b/lib/libc/gen/daemon.3 index cced3ceabb2..7d95dd8c2a2 100644 --- a/lib/libc/gen/daemon.3 +++ b/lib/libc/gen/daemon.3 @@ -28,7 +28,7 @@ .\" @(#)daemon.3 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd June 9, 1993 +.Dd December 23, 2017 .Dt DAEMON 3 .Os .Sh NAME @@ -40,6 +40,8 @@ .In stdlib.h .Ft int .Fn daemon "int nochdir" "int noclose" +.Ft int +.Fn daemonfd "int chdirfd" "int nullfd" .Sh DESCRIPTION The .Fn daemon @@ -59,15 +61,39 @@ is non-zero, .Fn daemon will redirect standard input, standard output, and standard error to .Pa /dev/null . +.Pp +The +.Fn daemonfd +function is equivalent to the +.Fn daemon +function except that arguments are the descriptors for the current working +directory and to the descriptor to +.Pa /dev/null . +.Pp +If +.Fa chdirfd +is equal to +.Pq -1 +the current working directory is not changed. +.Pp +If +.Fa nullfd +is equals to +.Pq -1 +the redirection of standard input, standard output, and standard error is not +closed. .Sh RETURN VALUES -.Rv -std daemon +.Rv -std daemon daemonfd .Sh ERRORS The .Fn daemon +and +.Fn daemonfd function may fail and set .Va errno for any of the errors specified for the library functions .Xr fork 2 +.Xr open 2, and .Xr setsid 2 . .Sh SEE ALSO @@ -79,6 +105,10 @@ The .Fn daemon function first appeared in .Bx 4.4 . +The +.Fn daemonfd +function first appeared in +.Fx 12.0 . .Sh CAVEATS Unless the .Fa noclose diff --git a/lib/libc/gen/daemon.c b/lib/libc/gen/daemon.c index b105e7519b5..467f0027700 100644 --- a/lib/libc/gen/daemon.c +++ b/lib/libc/gen/daemon.c @@ -1,8 +1,9 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 1990, 1993 The Regents of the University of California. + * Copyright (c) 2017 Mariusz Zaborski + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -46,10 +47,9 @@ __FBSDID("$FreeBSD$"); #include "libc_private.h" int -daemon(int nochdir, int noclose) +daemonfd(int chdirfd, int nullfd) { struct sigaction osa, sa; - int fd; pid_t newgrp; int oerrno; int osa_ok; @@ -83,15 +83,39 @@ daemon(int nochdir, int noclose) return (-1); } - if (!nochdir) - (void)chdir("/"); + if (chdirfd != -1) + (void)fchdir(chdirfd); - if (!noclose && (fd = _open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { - (void)_dup2(fd, STDIN_FILENO); - (void)_dup2(fd, STDOUT_FILENO); - (void)_dup2(fd, STDERR_FILENO); - if (fd > 2) - (void)_close(fd); + if (nullfd != -1) { + (void)_dup2(nullfd, STDIN_FILENO); + (void)_dup2(nullfd, STDOUT_FILENO); + (void)_dup2(nullfd, STDERR_FILENO); } return (0); } + +int +daemon(int nochdir, int noclose) +{ + int chdirfd, nullfd, ret; + + if (!noclose) + nullfd = _open(_PATH_DEVNULL, O_RDWR, 0); + else + nullfd = -1; + + if (!nochdir) + chdirfd = _open("/", O_EXEC); + else + chdirfd = -1; + + ret = daemonfd(chdirfd, nullfd); + + if (chdirfd != -1) + _close(chdirfd); + + if (nullfd > 2) + _close(nullfd); + + return (ret); +}