2 Compile-time config options:
4 If you set a gid, then what 'setgroups' does is only add this
5 group to the supplementary group list. So you call it like:
7 ./setgroups some command
9 If you don't set, then you have to pass group IDs you wish to
10 take on, and command argument you wish to execute with the new
11 supplementary group set, separated by '--', like:
13 ./setgroups 199 1000 4256 -- some command
15 Set file capabilities after compiled:
16 setcaps cap_setgid+ep ./setgroups
20 #include <sys/types.h>
27 int main(int argc
, char ** argv
)
41 if(argc
< 2) errx(-1, "No command given.");
45 gidlist
= malloc(sz_gidlist
* sizeof(gid_t
));
46 if(gidlist
== NULL
) abort();
48 while((n_groups
= getgroups(sz_gidlist
, gidlist
)) == -1)
53 gidlist
= realloc(gidlist
, sz_gidlist
* sizeof(gid_t
));
54 if(gidlist
== NULL
) abort();
58 err(errno
, "getgroups");
62 #ifndef ONLY_ALLOWED_GID
65 for(aux1
= 1; aux1
< argc
; aux1
++)
67 if(strcmp(argv
[aux1
], "--") == 0) { aux1
++; break; }
71 if(aux1
>= argc
) errx(-1, "No command given.");
72 execargs
= &argv
[aux1
];
78 if(n_groups
+ n_set_groups
/* TODO: don't allocate memory for gids which will be removed */ > sz_gidlist
)
80 sz_gidlist
+= n_set_groups
;
81 gidlist
= realloc(gidlist
, sz_gidlist
* sizeof(gid_t
));
82 if(gidlist
== NULL
) abort();
85 #ifndef ONLY_ALLOWED_GID
86 for(aux1
= 0; aux1
< n_set_groups
; aux1
++)
89 set_gid
= strtol(argv
[1+aux1
], endptr
, 0);
90 if(*endptr
== argv
[1+aux1
] || **endptr
!= '\0') errx(-1, "Can not parse '%s' as GID", argv
[1+aux1
]);
91 if(errno
!= 0) err(errno
, "Can not parse '%s' as GID", argv
[1+aux1
]);
95 gidlist
[n_groups
- 2*n_removed_groups
+ aux1
] = (gid_t
)set_gid
;
100 for(aux2
= 0; aux2
< n_groups
- n_removed_groups
- backshift
+ aux1
; aux2
++)
102 if(gidlist
[aux2
] == -set_gid
) backshift
+= 1;
103 gidlist
[aux2
] = gidlist
[aux2
+ backshift
];
105 n_removed_groups
+= backshift
;
109 gidlist
[n_groups
] = ONLY_ALLOWED_GID
;
112 if(setgroups(n_groups
+ n_set_groups
- 2*n_removed_groups
, gidlist
) != 0)
114 err(errno
, "setgroups");
117 execvp(execargs
[0], execargs
);
118 err(errno
, "exec: %s", execargs
[0]);