]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #4300 from keszybz/mkosi
authorLennart Poettering <lennart@poettering.net>
Fri, 7 Oct 2016 07:58:25 +0000 (09:58 +0200)
committerGitHub <noreply@github.com>
Fri, 7 Oct 2016 07:58:25 +0000 (09:58 +0200)
Various mkosi bits

17 files changed:
TODO
man/systemd-system.conf.xml
src/basic/capability-util.c
src/basic/socket-util.c
src/basic/socket-util.h
src/basic/user-util.c
src/core/execute.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/system.conf
src/libsystemd/sd-bus/bus-common-errors.c
src/libsystemd/sd-device/sd-device.c
src/nspawn/nspawn.c
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h
src/udev/net/ethtool-util.c

diff --git a/TODO b/TODO
index f215a4944b82a63429ea851d9c784b643896d79d..9ca2736b2a88ead4764ae8d6ad897a9b68f2b865 100644 (file)
--- a/TODO
+++ b/TODO
@@ -32,6 +32,10 @@ Janitorial Clean-ups:
 
 Features:
 
+* in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us
+
+* enable LockMLOCK to take a percentage value relative to physical memory
+
 * switch to ProtectSystem=strict for all our long-running services where that's possible
 
 * introduce an "invocation ID" for units, that is randomly generated, and
index 1bb40fd234aac4b34b3001fd2c675cb20bf801c5..a268397d09ba77e08f0508fd46aae4ff262003cf 100644 (file)
         arguments.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>CtrlAltDelBurstAction=</varname></term>
+
+        <listitem><para>Defines what action will be performed
+        if user presses Ctr-Alt-Delete more than 7 times in 2s.
+        Can be set to <literal>reboot-force</literal>, <literal>poweroff-force</literal>
+        or disabled with <literal>ignore</literal>. Defaults to
+        <literal>reboot-force</literal>.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>CPUAffinity=</varname></term>
 
index f8db6e02123e988dd885ff017ae8ec66ec48ea0a..c3de20a0e866baa2baa0450c8f36eb29c39bad85 100644 (file)
@@ -296,8 +296,9 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
         if (setresgid(gid, gid, gid) < 0)
                 return log_error_errno(errno, "Failed to change group ID: %m");
 
-        if (maybe_setgroups(0, NULL) < 0)
-                return log_error_errno(errno, "Failed to drop auxiliary groups list: %m");
+        r = maybe_setgroups(0, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to drop auxiliary groups list: %m");
 
         /* Ensure we keep the permitted caps across the setresuid() */
         if (prctl(PR_SET_KEEPCAPS, 1) < 0)
index 5c829e0e7e1a34b0340ceec08b400e1ec3b01b20..1662c047050aae55c49dc3d059a001194dd6795e 100644 (file)
@@ -1060,3 +1060,20 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
 
         return NULL;
 }
+
+int socket_ioctl_fd(void) {
+        int fd;
+
+        /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
+         * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
+         * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
+         * generic AF_NETLINK. */
+
+        fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+        if (fd < 0)
+                fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);
+        if (fd < 0)
+                return -errno;
+
+        return fd;
+}
index 2536b085f9551e1facb20015440124edaf5bb994..2ef572badb51ee644b68082447f4480c3161769b 100644 (file)
@@ -154,3 +154,5 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
                          1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
                          strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
         })
+
+int socket_ioctl_fd(void);
index 16496fccfa4b75d51f52b91c3f2147efa29bc4b0..de6c93056eca7c140241fe834520b9621804f1dc 100644 (file)
@@ -460,9 +460,11 @@ int get_shell(char **_s) {
 }
 
 int reset_uid_gid(void) {
+        int r;
 
-        if (maybe_setgroups(0, NULL) < 0)
-                return -errno;
+        r = maybe_setgroups(0, NULL);
+        if (r < 0)
+                return r;
 
         if (setresgid(0, 0, 0) < 0)
                 return -errno;
@@ -605,25 +607,30 @@ bool valid_home(const char *p) {
 }
 
 int maybe_setgroups(size_t size, const gid_t *list) {
-        static int cached_can_setgroups = -1;
-        /* check if setgroups is allowed before we try to drop all the auxiliary groups */
-        if (size == 0) {
-                if (cached_can_setgroups < 0) {
-                        _cleanup_free_ char *setgroups_content = NULL;
-                        int r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
-                        if (r < 0 && errno != ENOENT)
-                                return r;
-                        if (r < 0) {
-                                /* old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
-                                cached_can_setgroups = true;
-                        } else {
-                                cached_can_setgroups = streq(setgroups_content, "allow");
-                                if (!cached_can_setgroups)
-                                        log_debug("skip setgroups, /proc/self/setgroups is set to 'deny'");
-                        }
-                }
-                if (!cached_can_setgroups)
+        int r;
+
+        /* Check if setgroups is allowed before we try to drop all the auxiliary groups */
+        if (size == 0) { /* Dropping all aux groups? */
+                _cleanup_free_ char *setgroups_content = NULL;
+                bool can_setgroups;
+
+                r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
+                if (r == -ENOENT)
+                        /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
+                        can_setgroups = true;
+                else if (r < 0)
+                        return r;
+                else
+                        can_setgroups = streq(setgroups_content, "allow");
+
+                if (!can_setgroups) {
+                        log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
                         return 0;
+                }
         }
-        return setgroups(size, list);
+
+        if (setgroups(size, list) < 0)
+                return -errno;
+
+        return 0;
 }
index 019ff8490bb12fbde0526732648e60c3aac5bab2..d5c4e60796907f88ec68c078a64f9612e2514707 100644 (file)
@@ -781,9 +781,10 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
                         k++;
                 }
 
-                if (maybe_setgroups(k, gids) < 0) {
+                r = maybe_setgroups(k, gids);
+                if (r < 0) {
                         free(gids);
-                        return -errno;
+                        return r;
                 }
 
                 free(gids);
@@ -843,6 +844,7 @@ static int setup_pam(
                 const char *name,
                 const char *user,
                 uid_t uid,
+                gid_t gid,
                 const char *tty,
                 char ***env,
                 int fds[], unsigned n_fds) {
@@ -948,8 +950,14 @@ static int setup_pam(
                  * and this will make PR_SET_PDEATHSIG work in most cases.
                  * If this fails, ignore the error - but expect sd-pam threads
                  * to fail to exit normally */
+
+                r = maybe_setgroups(0, NULL);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to setgroups() in sd-pam: %m");
+                if (setresgid(gid, gid, gid) < 0)
+                        log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m");
                 if (setresuid(uid, uid, uid) < 0)
-                        log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m");
+                        log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m");
 
                 (void) ignore_signals(SIGPIPE, -1);
 
@@ -2413,7 +2421,7 @@ static int exec_child(
                 }
 
                 if (context->pam_name && username) {
-                        r = setup_pam(context->pam_name, username, uid, context->tty_path, &accum_env, fds, n_fds);
+                        r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
                         if (r < 0) {
                                 *exit_status = EXIT_PAM;
                                 return r;
index be0cb0b6d1da78c2121c7d247ca8da19c160bd59..6fe440277ecca6237aad07ff04cf3017b6ff5f18 100644 (file)
@@ -131,6 +131,7 @@ static bool arg_default_memory_accounting = false;
 static bool arg_default_tasks_accounting = true;
 static uint64_t arg_default_tasks_max = UINT64_MAX;
 static sd_id128_t arg_machine_id = {};
+static CADBurstAction arg_cad_burst_action = CAD_BURST_ACTION_REBOOT;
 
 noreturn static void freeze_or_reboot(void) {
 
@@ -648,6 +649,8 @@ static int config_parse_join_controllers(const char *unit,
         return 0;
 }
 
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_cad_burst_action, cad_burst_action, CADBurstAction, "Failed to parse service restart specifier");
+
 static int parse_config_file(void) {
 
         const ConfigTableItem items[] = {
@@ -702,6 +705,7 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultMemoryAccounting",   config_parse_bool,             0, &arg_default_memory_accounting         },
                 { "Manager", "DefaultTasksAccounting",    config_parse_bool,             0, &arg_default_tasks_accounting          },
                 { "Manager", "DefaultTasksMax",           config_parse_tasks_max,        0, &arg_default_tasks_max                 },
+                { "Manager", "CtrlAltDelBurstAction",     config_parse_cad_burst_action, 0, &arg_cad_burst_action},
                 {}
         };
 
@@ -1794,6 +1798,7 @@ int main(int argc, char *argv[]) {
         m->initrd_timestamp = initrd_timestamp;
         m->security_start_timestamp = security_start_timestamp;
         m->security_finish_timestamp = security_finish_timestamp;
+        m->cad_burst_action = arg_cad_burst_action;
 
         manager_set_defaults(m);
         manager_set_show_status(m, arg_show_status);
index dd0d1fa984cb2ff1106fa81c417f1106ad812de2..5253cb3712a35650b0d42179879044ad4473a501 100644 (file)
@@ -1894,6 +1894,35 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) {
         return r;
 }
 
+static void manager_handle_ctrl_alt_del(Manager *m) {
+        /* If the user presses C-A-D more than
+         * 7 times within 2s, we reboot/shutdown immediately,
+         * unless it was disabled in system.conf */
+
+        if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == CAD_BURST_ACTION_IGNORE)
+                manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
+        else {
+                switch (m->cad_burst_action) {
+
+                case CAD_BURST_ACTION_REBOOT:
+                        m->exit_code = MANAGER_REBOOT;
+                        break;
+
+                case CAD_BURST_ACTION_POWEROFF:
+                        m->exit_code = MANAGER_POWEROFF;
+                        break;
+
+                default:
+                        assert_not_reached("Unknown action.");
+                }
+
+                log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
+                                cad_burst_action_to_string(m->cad_burst_action));
+                status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
+                                cad_burst_action_to_string(m->cad_burst_action));
+        }
+}
+
 static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
         Manager *m = userdata;
         ssize_t n;
@@ -1945,19 +1974,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
 
                 case SIGINT:
                         if (MANAGER_IS_SYSTEM(m)) {
-
-                                /* If the user presses C-A-D more than
-                                 * 7 times within 2s, we reboot
-                                 * immediately. */
-
-                                if (ratelimit_test(&m->ctrl_alt_del_ratelimit))
-                                        manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
-                                else {
-                                        log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
-                                        status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
-                                        m->exit_code = MANAGER_REBOOT;
-                                }
-
+                                manager_handle_ctrl_alt_del(m);
                                 break;
                         }
 
@@ -3544,3 +3561,11 @@ static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);
+
+static const char *const cad_burst_action_table[_CAD_BURST_ACTION_MAX] = {
+        [CAD_BURST_ACTION_IGNORE] = "ignore",
+        [CAD_BURST_ACTION_REBOOT] = "reboot-force",
+        [CAD_BURST_ACTION_POWEROFF] = "poweroff-force",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cad_burst_action, CADBurstAction);
index a592f1cb941a5010f9528dc66e4b51305cbdf037..495440b44624a33f522676ec8d6d884e95bdbcfe 100644 (file)
@@ -62,6 +62,14 @@ typedef enum ManagerExitCode {
         _MANAGER_EXIT_CODE_INVALID = -1
 } ManagerExitCode;
 
+typedef enum CADBurstAction {
+        CAD_BURST_ACTION_IGNORE,
+        CAD_BURST_ACTION_REBOOT,
+        CAD_BURST_ACTION_POWEROFF,
+        _CAD_BURST_ACTION_MAX,
+        _CAD_BURST_ACTION_INVALID = -1
+} CADBurstAction;
+
 typedef enum StatusType {
         STATUS_TYPE_EPHEMERAL,
         STATUS_TYPE_NORMAL,
@@ -304,8 +312,9 @@ struct Manager {
         Hashmap *uid_refs;
         Hashmap *gid_refs;
 
-        /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */
+        /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */
         RateLimit ctrl_alt_del_ratelimit;
+        CADBurstAction cad_burst_action;
 
         const char *unit_log_field;
         const char *unit_log_format_string;
@@ -398,3 +407,6 @@ void manager_deserialize_gid_refs_one(Manager *m, const char *value);
 
 const char *manager_state_to_string(ManagerState m) _const_;
 ManagerState manager_state_from_string(const char *s) _pure_;
+
+const char *cad_burst_action_to_string(CADBurstAction a) _const_;
+CADBurstAction cad_burst_action_from_string(const char *s) _pure_;
index c6bb050aaccce4bc1524f8b85c31240dc4897e68..746572b7ff25db7c0c54028a3a2b49ce9a152777 100644 (file)
@@ -21,6 +21,7 @@
 #CrashChangeVT=no
 #CrashShell=no
 #CrashReboot=no
+#CtrlAltDelBurstAction=reboot-force
 #CPUAffinity=1 2
 #JoinControllers=cpu,cpuacct net_cls,net_prio
 #RuntimeWatchdogSec=0
index a69193aa32d6103ec9ea134a947b7cfa4e4ca438..9cc28ed5646a0022d1e93125f77dacabbb60358d 100644 (file)
@@ -52,6 +52,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID,           ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS,               EEXIST),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING,        ENOSYS),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING,         ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING,        ENXIO),
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION,              ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID,           ENXIO),
@@ -64,6 +66,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN,             EINVAL),
         SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS,        EINPROGRESS),
         SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,     EOPNOTSUPP),
+        SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY,                 EBUSY),
 
         SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED,  EALREADY),
 
@@ -82,6 +85,25 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY,                    EBUSY),
         SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN,                 ENETDOWN),
 
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR",               EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL",              EHOSTDOWN),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN",              ENXIO),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP",                ENOSYS),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED",               EACCES),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN",              EEXIST),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET",                EEXIST),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET",               ENOENT),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH",               EACCES),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE",               EREMOTE),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS",               EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY",                EKEYREJECTED),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME",               EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE",               EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME",               EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG",                EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC",              EBADMSG),
+        SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE",             EBADR),
+
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER,             ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS,         EBUSY),
 
index 0c4ad966bd4fb6c435d7e39b78caffecc76da5ec..411453e08d887d62e9af005a9d6ee7e515344ba8 100644 (file)
@@ -36,6 +36,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "set.h"
+#include "socket-util.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -629,9 +630,9 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
                 if (r < 0)
                         return r;
 
-                sk = socket(PF_INET, SOCK_DGRAM, 0);
+                sk = socket_ioctl_fd();
                 if (sk < 0)
-                        return -errno;
+                        return sk;
 
                 r = ioctl(sk, SIOCGIFNAME, &ifr);
                 if (r < 0)
index 9a8274c8de3f781b4a436810ca5a71d68aac2827..a08377b3a3e3d9eeaf3dc1c7866971dc535956eb 100644 (file)
@@ -3830,7 +3830,7 @@ int main(int argc, char *argv[]) {
                 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
                 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
-                ContainerStatus container_status;
+                ContainerStatus container_status = 0;
                 char last_char = 0;
                 int ifi = 0;
                 ssize_t l;
index a8ad8fe342b88a919863ca09ec0718948b39010c..337a8c473fb84810f60e44ce15b7d57c17ec8ac4 100644 (file)
@@ -2143,7 +2143,7 @@ int dns_packet_extract(DnsPacket *p) {
 
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-                        bool cache_flush;
+                        bool cache_flush = false;
 
                         r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
                         if (r < 0)
@@ -2289,6 +2289,7 @@ static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
         [DNS_RCODE_BADNAME] = "BADNAME",
         [DNS_RCODE_BADALG] = "BADALG",
         [DNS_RCODE_BADTRUNC] = "BADTRUNC",
+        [DNS_RCODE_BADCOOKIE] = "BADCOOKIE",
 };
 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
 
index 7b7d4e14c9689322cada0137e46e959fe5197bed..054dc88a85eeac796e4a7014bfd3755d4485923d 100644 (file)
@@ -263,6 +263,7 @@ enum {
         DNS_RCODE_BADNAME = 20,
         DNS_RCODE_BADALG = 21,
         DNS_RCODE_BADTRUNC = 22,
+        DNS_RCODE_BADCOOKIE = 23,
         _DNS_RCODE_MAX_DEFINED,
         _DNS_RCODE_MAX = 4095 /* 4 bit rcode in the header plus 8 bit rcode in OPT, makes 12 bit */
 };
index b1aa0223fd659b227cb4a8e5a3d0091b957807ee..708a66557605dc7fb6ef2c994b3fa7f9874b9598 100644 (file)
@@ -25,6 +25,7 @@
 #include "conf-parser.h"
 #include "ethtool-util.h"
 #include "log.h"
+#include "socket-util.h"
 #include "string-table.h"
 #include "strxcpyx.h"
 #include "util.h"
@@ -59,10 +60,9 @@ int ethtool_connect(int *ret) {
 
         assert_return(ret, -EINVAL);
 
-        fd = socket(PF_INET, SOCK_DGRAM, 0);
+        fd = socket_ioctl_fd();
         if (fd < 0)
-                return -errno;
-
+                return fd;
         *ret = fd;
 
         return 0;