Skip to content

Instantly share code, notes, and snippets.

@hxy9243
Last active August 29, 2015 14:06
Show Gist options
  • Save hxy9243/6c030cc3ec2b6cd7b8d6 to your computer and use it in GitHub Desktop.
Save hxy9243/6c030cc3ec2b6cd7b8d6 to your computer and use it in GitHub Desktop.
capability wrapper
a.out
out
*.txt
\#*#
~
/*
* descript:
* This is is a capability library wrapper for linux,
* see more details, please refer to libcap and
* <sys/capability.h> for more details.
*
* dependency: libcap
* link flag: -lcap
*
* author: Hu Xiaoyu
* created: Sep. 20 2014
*/
#include "priv.h"
/*
* Raise the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_raise (const int count, ...) {
int i;
cap_t cap;
cap_value_t cap_v;
cap_value_t *cap_v_list;
va_list arglist;
// alloca mem for cap_v_list, return error if count is oversized
if (count > CAP_LAST_CAP){
return -1;
}
cap_v_list = (cap_value_t *)alloca (sizeof (cap_value_t) * count);
// get the capability of the current process
if ( (cap = cap_get_proc ()) == NULL ){
return -1;
}
// set cap_v_list to effective flag of capability variable
va_start (arglist, count);
for (i = 0; i < count; i ++){
cap_v = va_arg (arglist, int);
cap_v_list[i] = cap_v;
}
va_end (arglist);
// set the flag of cap to value in cap_v_list
if ( cap_set_flag (cap,
CAP_EFFECTIVE,
count,
cap_v_list,
CAP_SET) != 0){
cap_free (cap);
return -1;
}
// set the capability to current proc
if ( cap_set_proc (cap) < 0){
cap_free (cap);
return -1;
}
cap_free (cap);
return 0;
}
/*
* Raise the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_lower (const int count, ...) {
int i;
cap_t cap;
cap_value_t cap_v;
cap_value_t *cap_v_list;
va_list arglist;
// alloca mem for cap_v_list, return error if count is oversized
if (count > CAP_LAST_CAP){
return -1;
}
cap_v_list = (cap_value_t *)alloca (sizeof (cap_value_t) * count);
// get the capability of the current process
if ( (cap = cap_get_proc ()) == NULL ){
return -1;
}
// set cap_v_list to effective flag of capability variable
va_start (arglist, count);
for (i = 0; i < count; i ++){
cap_v = va_arg (arglist, int);
cap_v_list[i] = cap_v;
}
va_end (arglist);
// set the flag of cap to value in cap_v_list
if ( cap_set_flag (cap,
CAP_EFFECTIVE,
count,
cap_v_list,
CAP_CLEAR) != 0){
cap_free (cap);
return -1;
}
// set the capability to current proc
if ( cap_set_proc (cap) < 0){
cap_free (cap);
return -1;
}
cap_free (cap);
return 0;
}
/*
* Drop the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_drop (const int count, ...) {
int i;
cap_t cap;
cap_value_t cap_v;
cap_value_t *cap_v_list;
va_list arglist;
// alloca mem for cap_v_list, return error if count is oversized
if (count > CAP_LAST_CAP){
return -1;
}
cap_v_list = (cap_value_t *)alloca (sizeof (cap_value_t) * count);
// get the capability of the current process
if ( (cap = cap_get_proc ()) == NULL ){
return -1;
}
// set cap_v_list to effective flag of capability variable
va_start (arglist, count);
for (i = 0; i < count; i ++){
cap_v = va_arg (arglist, int);
cap_v_list[i] = cap_v;
}
va_end (arglist);
// set the flag of cap to value in cap_v_list
if ( cap_set_flag (cap,
CAP_EFFECTIVE,
count,
cap_v_list,
CAP_CLEAR) != 0){
cap_free (cap);
return -1;
}
if ( cap_set_flag (cap,
CAP_PERMITTED,
count,
cap_v_list,
CAP_CLEAR) != 0){
cap_free (cap);
return -1;
}
// set the capability to current proc
if ( cap_set_proc (cap) < 0){
cap_free (cap);
return -1;
}
cap_free (cap);
return 0;
}
/*
* Drop all the capabilities in the current list
* for the current thread.
* return: 0 on success
* -1 on any error
*/
int priv_lowerall () {
int i;
cap_t cap;
cap_value_t cap_v;
cap_value_t *cap_v_list;
va_list arglist;
// get the capability of the current process
if ( (cap = cap_get_proc ()) == NULL ){
return -1;
}
cap_v_list = (cap_value_t *)alloca (sizeof (cap_value_t) * CAP_NUM);
// set cap_v_list to effective flag of capability variable
for (i = 0; i < CAP_NUM; i ++){
cap_v_list[i] = i;
}
// set the flag of cap to value in cap_v_list
if ( cap_set_flag (cap,
CAP_EFFECTIVE,
CAP_NUM,
cap_v_list,
CAP_CLEAR) != 0){
cap_free (cap);
return -1;
}
// set the capability to current proc
if ( cap_set_proc (cap) < 0){
cap_free (cap);
return -1;
}
cap_free (cap);
return 0;
}
/*
* descript:
* This is is a capability library wrapper for linux,
* see more details, please refer to libcap and
* <sys/capability.h> for more details.
* Link with: -lcap
*
* author: Hu Xiaoyu
* created: Sep. 20 2014
*/
#ifndef __CAP_H__
#define __CAP_H__
#define CAP_NUM (CAP_LAST_CAP + 1)
#include <sys/capability.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
/*
* Raise the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_raise (const int count, ...);
/*
* Raise the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_lower (const int count, ...);
/*
* Raise the capability in the current list
* for the current thread.
* param: const int count - total number of capabilities for operation;
* const cap_value_t cap - capability values defined in
* <linux/capability.h>
*
* return: 0 on success
* -1 on any error
*/
int priv_drop (const int count, ...);
/*
* Drop all the capabilities in the current list
* for the current thread.
* return: 0 on success
* -1 on any error
*/
int priv_lowerall ();
#endif
/*
* A small test case for cap wrapper library
* Compile with gcc test.c priv.c -lcap -o test
*/
#include <stdio.h>
#include "priv.h"
#include <unistd.h>
int main (int argc, char** argv){
int i;
cap_t cap;
cap_value_t cap_v;
cap_flag_value_t value;
if ( priv_lower (9,
CAP_AUDIT_CONTROL,
CAP_SYSLOG,
CAP_FOWNER,
CAP_FSETID,
CAP_SYS_BOOT,
CAP_SYS_CHROOT,
CAP_CHOWN,
CAP_DAC_OVERRIDE,
CAP_DAC_READ_SEARCH
) != 0 ){
fprintf (stderr, "Error dropping cap 0\n");
}
if ( priv_drop (3,
CAP_SYS_ADMIN,
CAP_AUDIT_WRITE,
CAP_SYS_BOOT) != 0){
fprintf (stderr, "Error raising cap 1\n");
}
if ( priv_raise (9,
CAP_AUDIT_CONTROL,
CAP_SYSLOG,
CAP_FOWNER,
CAP_FSETID,
CAP_SYS_BOOT,
CAP_CHOWN,
CAP_SYS_CHROOT,
CAP_AUDIT_WRITE,
CAP_SYS_BOOT) != 0){
fprintf (stderr, "Error raising cap 2\n");
}
if ( priv_lowerall() < 0 ){
fprintf (stderr, "Error lowering all privs\n");
}
if ( priv_raise (1, CAP_CHOWN) < 0 ){
fprintf (stderr, "Error raising priv again\n");
}
cap = cap_get_proc();
printf ("pid %d\n", getpid ());
printf ("\tPERM\tINHERIT\tEFFECT\n");
for (i = 0; i <= CAP_LAST_CAP; i ++){
printf ("%d\t", i);
cap_get_flag (cap, i, CAP_PERMITTED, &value);
printf ("%d\t", value == CAP_SET);
cap_get_flag (cap, i, CAP_INHERITABLE, &value);
printf ("%d\t", value == CAP_SET);
cap_get_flag (cap, i, CAP_EFFECTIVE, &value);
printf ("%d\t", value == CAP_SET);
printf ("\n");
}
cap_free (cap);
return 0;
}
/*
* Yet another test case for priv lib
* Testing if you still capable of chmod file after
* lowering CAP_FOWNER capability
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "priv.h"
int main (int argc, char **argv){
int status;
status = chmod ("foo.txt", S_IRUSR|S_IRGRP|S_IROTH);
printf ("Setting chmod before lowering priv: %s\n", status?"Fail":"Success");
status = priv_lower (1, CAP_FOWNER);
printf ("Setting priv %s\n", status?"Fail":"Success");
status = chmod ("foo.txt", S_IWUSR|S_IWGRP|S_IWOTH);
printf ("Setting chmod after lowering priv: %s\n", status?"Fail":"Success");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment