chiark / gitweb /
bus-proxyd: handle -ESRCH and -ENXIO gracefully
[elogind.git] / src / bus-proxyd / bus-proxyd.c
index 2e34cc9394e078742ac8a97670b782e90a9a6171..d15bd83514f5c5789f2a80b245817a6030d719f4 100644 (file)
@@ -45,6 +45,8 @@
 #include "def.h"
 #include "capability.h"
 #include "bus-policy.h"
+#include "bus-control.h"
+#include "smack-util.h"
 
 static char *arg_address = NULL;
 static char *arg_command_line_buffer = NULL;
@@ -958,6 +960,13 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *polic
         }
 }
 
+static int handle_policy_error(sd_bus_message *m, int r) {
+        if (r == -ESRCH || r == -ENXIO)
+                return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
+
+        return r;
+}
+
 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
         int r;
 
@@ -1002,7 +1011,7 @@ static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *p
                 }
 
                 if (granted) {
-                        /* Then check whether us, the recipient can recieve from the sender's name */
+                        /* Then check whether us (the recipient) can recieve from the sender's name */
                         if (strv_isempty(sender_names)) {
                                 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
                                         return 0;
@@ -1038,25 +1047,26 @@ static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *p
 
                 /* The message came from the legacy client, and is sent to kdbus. */
                 if (m->destination) {
-                        r = sd_bus_get_name_creds(to, m->destination,
-                                                  SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
-                                                  SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID, &destination_creds);
+                        r = bus_get_name_creds_kdbus(to, m->destination,
+                                                     SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
+                                                     SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
+                                                     true, &destination_creds);
                         if (r < 0)
-                                return r;
+                                return handle_policy_error(m, r);
 
                         r = sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
                         if (r < 0)
-                                return r;
+                                return handle_policy_error(m, r);
 
                         r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
                         if (r < 0)
-                                return r;
+                                return handle_policy_error(m, r);
 
                         (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
                         (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
                 }
 
-                /* First check if we, the sender can send to this name */
+                /* First check if we (the sender) can send to this name */
                 if (strv_isempty(destination_names)) {
                         if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
                                 granted = true;
@@ -1233,6 +1243,23 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) {
         return 0;
 }
 
+static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
+#ifdef HAVE_SMACK
+        int r = 0, k;
+
+        if (!mac_smack_use())
+                return 0;
+
+        if (new_label && its_pid > 0)
+                r = mac_smack_apply_pid(its_pid, new_label);
+
+        k = drop_capability(CAP_MAC_ADMIN);
+        return r < 0 ? r : k;
+#else
+        return 0;
+#endif
+}
+
 int main(int argc, char *argv[]) {
 
         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
@@ -1272,6 +1299,10 @@ int main(int argc, char *argv[]) {
         if (is_unix) {
                 (void) getpeercred(in_fd, &ucred);
                 (void) getpeersec(in_fd, &peersec);
+
+                r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
         }
 
         if (arg_drop_privileges) {