Fix headers
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / priv.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <inline-syscall.h>
21 #include <privP.h>
22 #include <sys/priocntl.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <stdarg.h>
26
27 DECLARE_INLINE_SYSCALL (int, privsys, int code, priv_op_t op,
28     priv_ptype_t type, void *buf, size_t bufsize);
29
30 /* Docs: http://docs.sun.com/app/docs/doc/816-5168/6mbb3hrjc
31          http://docs.sun.com/app/docs/doc/816-5168/6mbb3hrj7
32          http://docs.sun.com/app/docs/doc/816-5167/setppriv-2 */
33
34 __libc_lock_define_initialized_recursive (, __priv_lock);
35 libc_freeres_ptr (static priv_impl_info_t *__info);
36
37 /* Note: Almost everything that uses getprivimplinfo assumes it won't fail so
38    we assert that this call succeeds.  */
39 const priv_impl_info_t * getprivimplinfo (void)
40 {
41   if (__info)
42     return __info;
43
44   __libc_lock_lock_recursive (__priv_lock);
45
46   /* First call: get header.  */
47   priv_impl_info_t _info;
48   int res = INLINE_SYSCALL (privsys, 5, SYS_SUB_getimplinfo, 0, 0, &_info,
49       sizeof(_info));
50   if (res == 0)
51     {
52       /* Second call: alloc and get full priv_impl_info_t.  */
53       size_t info_size = PRIV_IMPL_INFO_SIZE (&_info);
54       __info = malloc (info_size);
55       assert (__info);
56       res = INLINE_SYSCALL (privsys, 5, SYS_SUB_getimplinfo, 0, 0, __info,
57           info_size);
58       assert (res == 0);
59     }
60
61   __libc_lock_unlock_recursive (__priv_lock);
62   return __info;
63 }
64
65
66 int getppriv (priv_ptype_t which, priv_set_t *set)
67 {
68   int setn = priv_getsetbyname (which);
69   if (setn == -1)
70     return -1;
71
72   return INLINE_SYSCALL (privsys, 5, SYS_SUB_getppriv, 0, (priv_ptype_t)setn,
73       (void *)set, __PRIVSETSIZE);
74 }
75
76
77 int setppriv (priv_op_t op, priv_ptype_t which, const priv_set_t *set)
78 {
79   int setn = priv_getsetbyname (which);
80   if (setn == -1)
81     return -1;
82
83   return INLINE_SYSCALL (privsys, 5, SYS_SUB_setppriv, op, (priv_ptype_t)setn,
84       (void *)set, __PRIVSETSIZE);
85 }
86
87
88 priv_set_t *priv_allocset (void)
89 {
90   return malloc (__PRIVSETSIZE);
91 }
92
93
94 void priv_freeset (priv_set_t *sp)
95 {
96   free (sp);
97 }
98
99
100 int priv_getbyname (const char *privname)
101 {
102   const priv_data_t *pd = __priv_parse_data_cached ();
103   if (!pd)
104     return -1;
105
106   for (uint32_t i = 0; i < pd->pd_privnames_cnt; i++)
107     {
108       if (strcasecmp (pd->pd_privnames[i], privname) == 0)
109         return i;
110     }
111
112   __set_errno (EINVAL);
113   return -1;
114 }
115
116
117 const char *priv_getbynum (int privnum)
118 {
119   const priv_data_t *pd = __priv_parse_data_cached ();
120   if (!pd)
121     return NULL;
122
123   if (privnum < 0 || privnum >= pd->pd_privnames_cnt)
124     {
125       __set_errno (EINVAL);
126       return NULL;
127     }
128
129   return pd->pd_privnames[privnum];
130 }
131
132
133 int priv_getsetbyname (const char *privsetname)
134 {
135   const priv_data_t *pd = __priv_parse_data_cached ();
136   if (!pd)
137     return -1;
138
139   for (uint32_t i = 0; i < pd->pd_setnames_cnt; i++)
140     {
141       if (strcasecmp (pd->pd_setnames[i], privsetname) == 0)
142         return i;
143     }
144
145   __set_errno (EINVAL);
146   return -1;
147 }
148
149
150 const char *priv_getsetbynum (int privsetnum)
151 {
152   const priv_data_t *pd = __priv_parse_data_cached ();
153   if (!pd)
154     return NULL;
155
156   if (privsetnum < 0 || privsetnum >= pd->pd_setnames_cnt)
157     {
158       __set_errno (EINVAL);
159       return NULL;
160     }
161
162   return pd->pd_setnames[privsetnum];
163 }
164
165
166 void priv_emptyset (priv_set_t *sp)
167 {
168   memset (sp, 0, __PRIVSETSIZE);
169 }
170
171
172 void priv_fillset(priv_set_t *sp)
173 {
174   memset (sp, ~0, __PRIVSETSIZE);
175 }
176
177
178 void priv_copyset (const priv_set_t *src, priv_set_t *dst)
179 {
180   memcpy (dst, src, __PRIVSETSIZE);
181 }
182
183
184 int priv_addset (priv_set_t *sp, const char *priv)
185 {
186   int privn = priv_getbyname (priv);
187   if (privn == -1)
188     return -1;
189
190   ((priv_chunk_t *)sp)[__PRIVELT (privn)] |= __PRIVMASK (privn);
191   return 0;
192 }
193
194
195 int priv_delset (priv_set_t *sp, const char *priv)
196 {
197   int privn = priv_getbyname (priv);
198   if (privn == -1)
199     return -1;
200
201   ((priv_chunk_t *)sp)[__PRIVELT (privn)] &= ~__PRIVMASK (privn);
202   return 0;
203 }
204
205
206 void priv_intersect (const priv_set_t *src, priv_set_t *dst)
207 {
208   priv_chunk_t *pcsrc = (priv_chunk_t *)src;
209   priv_chunk_t *pcdst = (priv_chunk_t *)dst;
210   for (int i = 0; i < __PRIVSETCHUNKS; i++)
211     pcdst[__PRIVELT (i)] &= pcsrc[__PRIVELT (i)];
212 }
213
214
215 void priv_union (const priv_set_t *src, priv_set_t *dst)
216 {
217   priv_chunk_t *pcsrc = (priv_chunk_t *)src;
218   priv_chunk_t *pcdst = (priv_chunk_t *)dst;
219   for (int i = 0; i < __PRIVSETCHUNKS; i++)
220     pcdst[__PRIVELT (i)] |= pcsrc[__PRIVELT (i)];
221 }
222
223
224 void priv_inverse(priv_set_t *sp)
225 {
226   priv_chunk_t *pcsp = (priv_chunk_t *)sp;
227   for (int i = 0; i < __PRIVSETCHUNKS; i++)
228     pcsp[i] = ~pcsp[i];
229 }
230
231
232 boolean_t priv_isemptyset (const priv_set_t *sp)
233 {
234   priv_chunk_t *pcsp = (priv_chunk_t *)sp;
235   for (int i = 0; i < __PRIVSETCHUNKS; i++)
236     if (pcsp[i])
237       return B_FALSE;
238   return B_TRUE;
239 }
240
241
242 boolean_t priv_isfullset (const priv_set_t *sp)
243 {
244   priv_chunk_t *pcsp = (priv_chunk_t *)sp;
245   for (int i = 0; i < __PRIVSETCHUNKS; i++)
246     if (~pcsp[i])
247       return B_FALSE;
248   return B_TRUE;
249 }
250
251
252 boolean_t priv_ismember (const priv_set_t *sp, const char *priv)
253 {
254   int privn = priv_getbyname (priv);
255   if (privn == -1)
256     return B_FALSE;
257
258   return (((priv_chunk_t *)sp)[__PRIVELT (privn)] & __PRIVMASK (privn)) ?
259       B_TRUE : B_FALSE;
260 }
261
262
263 boolean_t priv_issubset (const priv_set_t *src, const priv_set_t *dst)
264 {
265   priv_chunk_t *pcsrc = (priv_chunk_t *)src;
266   priv_chunk_t *pcdst = (priv_chunk_t *)dst;
267   for (int i = 0; i < __PRIVSETCHUNKS; i++)
268     if ((pcsrc[__PRIVELT (i)] & pcdst[__PRIVELT (i)]) != pcsrc[__PRIVELT (i)])
269       return B_FALSE;
270   return B_TRUE;
271 }
272
273
274 int priv_set (priv_op_t op, priv_ptype_t which, ...)
275 {
276   va_list ap;
277   va_start (ap, which);
278
279   priv_set_t *pset = priv_allocset ();
280   if (!pset)
281     return -1;
282
283   const char *priv;
284   while ((priv = va_arg (ap, const char *)))
285     {
286       if (priv_addset (pset, priv) == -1)
287         return -1;
288     }
289
290   int ret;
291   if (which == NULL)
292     {
293       /* Set all sets.  */
294       for (int i = 0; i < __PRIVSETCHUNKS; i++)
295         {
296           ret = setppriv (op, which, pset);
297           if (ret == -1)
298             break;
299         }
300     }
301   else
302     {
303       ret = setppriv (op, which, pset);
304     }
305
306   priv_freeset (pset);
307   return 0;
308 }
309
310 boolean_t priv_ineffect (const char *priv)
311 {
312   priv_set_t *pset = priv_allocset ();
313   if (!pset)
314     return B_FALSE;
315
316   int res = getppriv (PRIV_EFFECTIVE, pset);
317   if (res == -1)
318     return B_FALSE;
319
320   boolean_t ret = priv_ismember (pset, priv);
321
322   priv_freeset (pset);
323
324   return ret;
325 }