Re: [RFC PATCH 4/8] core: add missing SELinux checks for dbus methods

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Mi., 18. Dez. 2019 um 21:05 Uhr schrieb Stephen Smalley <sds@xxxxxxxxxxxxx>:
>
> On 12/18/19 9:28 AM, Christian Göttsche wrote:
> > Add new SELinux permissions `modify` and `listdynusers` to the class `service`.
> >    - modfiy checks altering operations, like `systemctl log-level debug` or `systemctl add-wants foo bar`.
> >    - listdynusers checks obtaining dynamic users, which is very common on systems using nss-systemd.
> >      Add a new permission to avoid undermining the `status` permission.
> >
> > Perform SELinux access checks for the following D-Bus exposed methods:
> >
> >    D-Bus interface         | c function name                    | SELinux permission verb
> >
> >    GetAfter / GetBefore    | bus_job_method_get_waiting_jobs    | status
> >    LogTarget               | property_set_log_target            | modify
> >    LogLevel                | property_set_log_level             | modify
> >    RuntimeWatchdocUSec     | property_set_runtime_watchdog      | modify
> >    ServiceWatchdogs        | bus_property_set_bool_wrapper      | modify
> >    GetUnit                 | method_get_unit                    | status
> >    GetUnitByPID            | method_get_unit_by_pid             | status
> >    GetUnitByControlGroup   | method_get_unit_by_control_group   | status
> >    LoadUnit                | method_load_unit                   | status
> >    ListUnitsByNames        | method_list_units_by_names         | status
> >    LookupDynamicUserByName | method_lookup_dynamic_user_by_name | listdynusers
> >    LookupDynamicUserByUID  | method_lookup_dynamic_user_by_uid  | listdynusers
> >    GetDynamicUsers         | method_get_dynamic_users           | listdynusers
> >    AddDependencyUnitFiles  | method_add_dependency_unit_files   | modify
> >    GetUnitFileLinks        | method_get_unit_file_links         | status
> >    Unref                   | bus_unit_method_unref              | modify
>
> If we are going to introduce new permissions or change existing ones, we
> may want to consider just defining a separate permission for every
> logical interface.  Then we can let the policy writer decide what
> matters to them and at what granularity they want to distinguish things,
> using macros/interfaces as appropriate to avoid needing to specify them
> all individually.
>
> Also, you may want to leverage the policy capability mechanism in
> userspace to permit compatible evolution of permission checks in the
> same manner it is presently used in the kernel for
> extended_socket_class, network_peer_controls, open_perms,
> nnp_nosuid_transition, etc.
>

This might be an idea, to preserve full backward compatibility.
While on it one could untangle the system security class.

Afaik this would require a SELinux userland and kernel update, to
introduce a new policy capability identifier?

>
> > ---
> >   src/core/dbus-job.c     |  4 ++
> >   src/core/dbus-manager.c | 89 ++++++++++++++++++++++++++++++++++++-----
> >   src/core/dbus-unit.c    |  4 ++
> >   3 files changed, 88 insertions(+), 9 deletions(-)
> >
> > diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
> > index a7d342257b..7b0b093757 100644
> > --- a/src/core/dbus-job.c
> > +++ b/src/core/dbus-job.c
> > @@ -71,6 +71,10 @@ int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_
> >           Job *j = userdata;
> >           int r, i, n;
> >
> > +        r = mac_selinux_unit_access_check(j->unit, message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           if (strstr(sd_bus_message_get_member(message), "After"))
> >                   n = job_get_after(j, &list);
> >           else
> > diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
> > index c751e84253..d2db6e4a61 100644
> > --- a/src/core/dbus-manager.c
> > +++ b/src/core/dbus-manager.c
> > @@ -121,6 +121,10 @@ static int property_set_log_target(
> >           assert(bus);
> >           assert(value);
> >
> > +        r = mac_selinux_access_check(value, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read(value, "s", &t);
> >           if (r < 0)
> >                   return r;
> > @@ -178,6 +182,10 @@ static int property_set_log_level(
> >           assert(bus);
> >           assert(value);
> >
> > +        r = mac_selinux_access_check(value, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read(value, "s", &t);
> >           if (r < 0)
> >                   return r;
> > @@ -282,6 +290,10 @@ static int property_set_runtime_watchdog(
> >
> >           assert_cc(sizeof(usec_t) == sizeof(uint64_t));
> >
> > +        r = mac_selinux_access_check(value, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read(value, "t", t);
> >           if (r < 0)
> >                   return r;
> > @@ -289,6 +301,24 @@ static int property_set_runtime_watchdog(
> >           return watchdog_set_timeout(t);
> >   }
> >
> > +static int bus_property_set_bool_wrapper(
> > +                sd_bus *bus,
> > +                const char *path,
> > +                const char *interface,
> > +                const char *property,
> > +                sd_bus_message *value,
> > +                void *userdata,
> > +                sd_bus_error *error) {
> > +
> > +        int r;
> > +
> > +        r = mac_selinux_access_check(value, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> > +        return bus_property_set_bool(bus, path, interface, property, value, userdata, error);
> > +}
> > +
> >   static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
> >           Unit *u;
> >           int r;
> > @@ -375,6 +405,10 @@ static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error
> >           if (r < 0)
> >                   return r;
> >
> > +        r = mac_selinux_unit_access_check(u, message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           return reply_unit_path(u, message, error);
> >   }
> >
> > @@ -413,6 +447,10 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu
> >           if (!u)
> >                   return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
> >
> > +        r = mac_selinux_unit_access_check(u, message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           return reply_unit_path(u, message, error);
> >   }
> >
> > @@ -488,6 +526,10 @@ static int method_get_unit_by_control_group(sd_bus_message *message, void *userd
> >           if (!u)
> >                   return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup);
> >
> > +        r = mac_selinux_unit_access_check(u, message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           return reply_unit_path(u, message, error);
> >   }
> >
> > @@ -510,6 +552,10 @@ static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_erro
> >           if (r < 0)
> >                   return r;
> >
> > +        r = mac_selinux_unit_access_check(u, message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           return reply_unit_path(u, message, error);
> >   }
> >
> > @@ -529,6 +575,7 @@ static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobTyp
> >           if (r < 0)
> >                   return r;
> >
> > +        /* bus_unit_method_start_generic() includes a mac_selinux check */
> >           return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error);
> >   }
> >
> > @@ -703,6 +750,10 @@ static int method_list_units_by_names(sd_bus_message *message, void *userdata, s
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read_strv(message, &units);
> >           if (r < 0)
> >                   return r;
> > @@ -1263,11 +1314,11 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
> >           assert(message);
> >           assert(m);
> >
> > -        r = verify_run_space("Refusing to reload", error);
> > +        r = mac_selinux_access_check(message, "reload", error);
> >           if (r < 0)
> >                   return r;
> >
> > -        r = mac_selinux_access_check(message, "reload", error);
> > +        r = verify_run_space("Refusing to reload", error);
> >           if (r < 0)
> >                   return r;
> >
> > @@ -1299,11 +1350,11 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
> >           assert(message);
> >           assert(m);
> >
> > -        r = verify_run_space("Refusing to reexecute", error);
> > +        r = mac_selinux_access_check(message, "reload", error);
> >           if (r < 0)
> >                   return r;
> >
> > -        r = mac_selinux_access_check(message, "reload", error);
> > +        r = verify_run_space("Refusing to reexecute", error);
> >           if (r < 0)
> >                   return r;
> >
> > @@ -1428,6 +1479,10 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "reboot", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           if (statvfs("/run/systemd", &svfs) < 0)
> >                   return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
> >
> > @@ -1441,10 +1496,6 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
> >                               format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
> >           }
> >
> > -        r = mac_selinux_access_check(message, "reboot", error);
> > -        if (r < 0)
> > -                return r;
> > -
> >           if (!MANAGER_IS_SYSTEM(m))
> >                   return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
> >
> > @@ -1636,6 +1687,10 @@ static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *use
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "listdynusers", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read_basic(message, 's', &name);
> >           if (r < 0)
> >                   return r;
> > @@ -1663,6 +1718,10 @@ static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *user
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "listdynusers", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           assert_cc(sizeof(uid) == sizeof(uint32_t));
> >           r = sd_bus_message_read_basic(message, 'u', &uid);
> >           if (r < 0)
> > @@ -1692,6 +1751,10 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "listdynusers", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           assert_cc(sizeof(uid_t) == sizeof(uint32_t));
> >
> >           if (!MANAGER_IS_SYSTEM(m))
> > @@ -2264,6 +2327,10 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
> >           assert(message);
> >           assert(m);
> >
> > +        r = mac_selinux_access_check(message, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = bus_verify_manage_unit_files_async(m, message, error);
> >           if (r < 0)
> >                   return r;
> > @@ -2300,6 +2367,10 @@ static int method_get_unit_file_links(sd_bus_message *message, void *userdata, s
> >           char **p;
> >           int runtime, r;
> >
> > +        r = mac_selinux_access_check(message, "status", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = sd_bus_message_read(message, "sb", &name, &runtime);
> >           if (r < 0)
> >                   return r;
> > @@ -2422,7 +2493,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
> >           /* The following item is an obsolete alias */
> >           SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN),
> >           SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0),
> > -        SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
> > +        SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool_wrapper, offsetof(Manager, service_watchdogs), 0),
> >           SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
> >           SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
> >           SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
> > diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
> > index 9477c47140..f86efaac3a 100644
> > --- a/src/core/dbus-unit.c
> > +++ b/src/core/dbus-unit.c
> > @@ -645,6 +645,10 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error
> >           assert(message);
> >           assert(u);
> >
> > +        r = mac_selinux_unit_access_check(u, message, "modify", error);
> > +        if (r < 0)
> > +                return r;
> > +
> >           r = bus_unit_track_remove_sender(u, message);
> >           if (r == -EUNATCH)
> >                   return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
> >
>




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux