From 01070b9e2ea34c485a9958b89af0d7e17fb310d3 Mon Sep 17 00:00:00 2001 From: Brian Bennett Date: Tue, 17 Feb 2015 23:24:15 +0000 Subject: [PATCH] lib: Fix POSIX capabilities on SunOS platforms When using POSIX capabilities on SunOS the capabilities are too restricitve resulting in quagga processes not being able to read their own config files. Credit goes to Oracle where this patch was originally authored and included in OpenSolaris. lib/privs.c: Include additional capabilities, better checking of missing capabilities. Fixes: #820 Acked-by: Greg Troxel Signed-off-by: David Lamparter --- lib/privs.c | 76 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/lib/privs.c b/lib/privs.c index e182543a63..f7269f4acc 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -2,7 +2,7 @@ * Zebra privileges. * * Copyright (C) 2003 Paul Jakma. - * Copyright (C) 2005 Sun Microsystems, Inc. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * * This file is part of GNU Zebra. * @@ -348,6 +348,26 @@ zprivs_caps_terminate (void) * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1 */ +static pset_t * +zprivs_caps_minimal () +{ + pset_t *minimal; + + if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL) + { + fprintf (stderr, "%s: couldn't get basic set!\n", __func__); + exit (1); + } + + /* create a minimal privilege set from the basic set */ + (void) priv_delset(minimal, PRIV_PROC_EXEC); + (void) priv_delset(minimal, PRIV_PROC_INFO); + (void) priv_delset(minimal, PRIV_PROC_SESSION); + (void) priv_delset(minimal, PRIV_FILE_LINK_ANY); + + return minimal; +} + /* convert zebras privileges to system capabilities */ static pset_t * zcaps2sys (zebra_capabilities_t *zcaps, int num) @@ -376,26 +396,34 @@ zcaps2sys (zebra_capabilities_t *zcaps, int num) int zprivs_change_caps (zebra_privs_ops_t op) { + pset_t *privset; /* should be no possibility of being called without valid caps */ assert (zprivs_state.syscaps_p); if (!zprivs_state.syscaps_p) + { + fprintf (stderr, "%s: Eek, missing privileged caps!", __func__); + exit (1); + } + + assert (zprivs_state.caps); + if (!zprivs_state.caps) { fprintf (stderr, "%s: Eek, missing caps!", __func__); exit (1); } - - /* to raise: copy original permitted into our working effective set - * to lower: just clear the working effective set + + /* to raise: copy original permitted as our working effective set + * to lower: copy regular effective set stored in zprivs_state.caps */ if (op == ZPRIVS_RAISE) - priv_copyset (zprivs_state.syscaps_p, zprivs_state.caps); + privset = zprivs_state.syscaps_p; else if (op == ZPRIVS_LOWER) - priv_emptyset (zprivs_state.caps); + privset = zprivs_state.caps; else return -1; - if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0) + if (setppriv (PRIV_SET, PRIV_EFFECTIVE, privset) != 0) return -1; return 0; @@ -423,15 +451,15 @@ zprivs_state_caps (void) } else { - if (priv_isemptyset (effective) == B_TRUE) + if (priv_isequalset (effective, zprivs_state.syscaps_p)) + result = ZPRIVS_RAISED; + else if (priv_isequalset (effective, zprivs_state.caps)) result = ZPRIVS_LOWERED; else - result = ZPRIVS_RAISED; + result = ZPRIVS_UNKNOWN; } - if (effective) - priv_freeset (effective); - + priv_freeset (effective); return result; } @@ -439,7 +467,7 @@ static void zprivs_caps_init (struct zebra_privs_t *zprivs) { pset_t *basic; - pset_t *empty; + pset_t *minimal; /* the specified sets */ zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p); @@ -467,14 +495,6 @@ zprivs_caps_init (struct zebra_privs_t *zprivs) priv_union (basic, zprivs_state.syscaps_p); priv_freeset (basic); - /* we need an empty set for 'effective', potentially for inheritable too */ - if ( (empty = priv_allocset()) == NULL) - { - fprintf (stderr, "%s: couldn't get empty set!\n", __func__); - exit (1); - } - priv_emptyset (empty); - /* Hey kernel, we know about privileges! * this isn't strictly required, use of setppriv should have same effect */ @@ -517,16 +537,19 @@ zprivs_caps_init (struct zebra_privs_t *zprivs) exit (1); } - /* now clear the effective set and we're ready to go */ - if (setppriv (PRIV_SET, PRIV_EFFECTIVE, empty)) + /* we need a minimal basic set for 'effective', potentially for inheritable too */ + minimal = zprivs_caps_minimal(); + + /* now set the effective set with a subset of basic privileges */ + if (setppriv (PRIV_SET, PRIV_EFFECTIVE, minimal)) { fprintf (stderr, "%s: error setting effective set!, %s\n", __func__, safe_strerror (errno) ); exit (1); } - /* we'll use this as our working-storage privset */ - zprivs_state.caps = empty; + /* we'll use the minimal set as our working-storage privset */ + zprivs_state.caps = minimal; /* set methods for the caller to use */ zprivs->change = zprivs_change_caps; @@ -538,8 +561,7 @@ zprivs_caps_terminate (void) { assert (zprivs_state.caps); - /* clear all capabilities */ - priv_emptyset (zprivs_state.caps); + /* clear all capabilities by using working-storage privset */ setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps); setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps); setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps); -- 2.39.5