[syslog-ng] [PATCH] Use CAP_SYSLOG instead of CAP_SYS_ADMIN, if available.
Gergely Nagy
algernon at balabit.hu
Sun May 8 12:23:04 CEST 2011
Balazs Scheidler <bazsi at balabit.hu> writes:
> I've some notes, please let me know if you or Serge would like to do
> that, or I should.
>
> Nothing extraordinary, the mass of the work has already been done, I
> just prefer some things a bit differently.
I'll be sending a patch in a few moments, but I've done a few things a
bit differently than you suggested, so I'd like to explain that in
advance.
>> /**
>> + * g_process_setup_caps(void)
>> + *
>> + * NOTE: polling /proc/kmsg requires cap_sys_admin, otherwise it'll always
>> + * indicate readability. Enabling/disabling cap_sys_admin on every poll
>> + * invocation seems to be too expensive. So I enable it for now.
>> + */
>> +void
>> +g_process_setup_caps(void)
>> +{
>> + int ret;
>> + gchar * capsstr = "cap_net_bind_service,cap_net_broadcast,cap_net_raw,"
>> + "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p "
>> + "cap_sys_admin=ep";
>> +#ifdef CAP_SYSLOG
>> + cap_t caps;
>> +
>> + /* Check whether cap_syslog exists. If not, get cap_sys_admin, else get
>> + * cap_syslog */
>> + caps = cap_from_text("cap_syslog=p");
>> + if (caps) {
>> + cap_free(caps);
>> + /* libcap knows it, does the kernel? */
>> + ret = prctl(PR_CAPBSET_READ, CAP_SYSLOG);
>> + if (ret != -1) {
>> + /* kernel knows cap_syslog! Use it */
>> + capsstr = "cap_net_bind_service,cap_net_broadcast,cap_net_raw,"
>> + "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p "
>> + "cap_syslog=ep";
>> + have_capsyslog = TRUE;
>> + }
>> + }
>> +#endif
>> +
>> + g_process_set_caps(capsstr);
>> +}
>
> I would prefer to construct the set of permissions needed for syslog-ng
> to be constructed in the main.c file, e.g. the detection code should be
> moved into a
>
> gboolean g_process_is_cap_supported(cap_t cap)
>
> Then in the main.c file (perhaps in a separate function), construct the
> required set of caps, and set by g_process_set_caps(). (e.g don't make
> it static and remove the g_process_setup_caps() stuff.
This is something I've done differently: I introduced
g_process_check_cap_syslog(), which checks for CAP_SYSLOG presence, and
sets have_capsyslog to TRUE if it is found. This was done so that
g_process_cap_modify() wouldn't have to do it itself.
But come to think of it, I could've done something like this (in
lib/gprocess.c):
static gint cap_syslog_override = -1;
And in g_process_cap_modify():
if (capability == CAP_SYSLOG)
{
if (cap_syslog_override != -1)
capability = cap_syslog_override;
else
{
if (g_process_is_cap_supported(CAP_SYSLOG))
cap_syslog_override = CAP_SYSLOG;
else
cap_syslog_override = CAP_SYS_ADMIN;
}
}
Or something similar...
This would have the advantage of having a generic
g_process_is_cap_supported(), with the downside of the code being
longer. And for reasons I can't properly explain, I like the
_check_cap_syslog() solution better.
> Also note that the user can override the capset of syslog-ng using the
> --caps option.
With my solution, that doesn't need special handling, I believe. But I
haven't tested all scenarios.
--
|8]
More information about the syslog-ng
mailing list