Add per UID interface support to resolv cache
Add methods to attach/detach UID ranges to a specific dns cache/interface. This mirrors the already existing code for attaching specific processes to specific interfaces but will be used to push all processes from a given user to a specific cache/interface. Change-Id: Ic24391e92d3ca46fcb46cc4fc53e13984dec40b3
This commit is contained in:
parent
3010061a53
commit
0c9bb49a9d
@ -1258,6 +1258,12 @@ typedef struct resolv_pidiface_info {
|
|||||||
char ifname[IF_NAMESIZE + 1];
|
char ifname[IF_NAMESIZE + 1];
|
||||||
struct resolv_pidiface_info* next;
|
struct resolv_pidiface_info* next;
|
||||||
} PidIfaceInfo;
|
} PidIfaceInfo;
|
||||||
|
typedef struct resolv_uidiface_info {
|
||||||
|
int low;
|
||||||
|
int high;
|
||||||
|
char ifname[IF_NAMESIZE + 1];
|
||||||
|
struct resolv_uidiface_info* next;
|
||||||
|
} UidIfaceInfo;
|
||||||
|
|
||||||
#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED)
|
#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED)
|
||||||
|
|
||||||
@ -1796,6 +1802,9 @@ static struct resolv_cache_info _res_cache_list;
|
|||||||
// List of pid iface pairs
|
// List of pid iface pairs
|
||||||
static struct resolv_pidiface_info _res_pidiface_list;
|
static struct resolv_pidiface_info _res_pidiface_list;
|
||||||
|
|
||||||
|
// List of uid iface pairs
|
||||||
|
static struct resolv_uidiface_info _res_uidiface_list;
|
||||||
|
|
||||||
// name of the current default inteface
|
// name of the current default inteface
|
||||||
static char _res_default_ifname[IF_NAMESIZE + 1];
|
static char _res_default_ifname[IF_NAMESIZE + 1];
|
||||||
|
|
||||||
@ -1805,6 +1814,9 @@ static pthread_mutex_t _res_cache_list_lock;
|
|||||||
// lock protecting the _res_pid_iface_list
|
// lock protecting the _res_pid_iface_list
|
||||||
static pthread_mutex_t _res_pidiface_list_lock;
|
static pthread_mutex_t _res_pidiface_list_lock;
|
||||||
|
|
||||||
|
// lock protecting the _res_uidiface_list
|
||||||
|
static pthread_mutex_t _res_uidiface_list_lock;
|
||||||
|
|
||||||
/* lookup the default interface name */
|
/* lookup the default interface name */
|
||||||
static char *_get_default_iface_locked();
|
static char *_get_default_iface_locked();
|
||||||
/* find the first cache that has an associated interface and return the name of the interface */
|
/* find the first cache that has an associated interface and return the name of the interface */
|
||||||
@ -1839,6 +1851,13 @@ static void _remove_pidiface_info_locked(int pid);
|
|||||||
/* get a resolv_pidiface_info structure from _res_pidiface_list with a certain pid */
|
/* get a resolv_pidiface_info structure from _res_pidiface_list with a certain pid */
|
||||||
static struct resolv_pidiface_info* _get_pid_iface_info_locked(int pid);
|
static struct resolv_pidiface_info* _get_pid_iface_info_locked(int pid);
|
||||||
|
|
||||||
|
/* remove a resolv_pidiface_info structure from _res_uidiface_list */
|
||||||
|
static int _remove_uidiface_info_locked(int low, int high);
|
||||||
|
/* check if a range [low,high] overlaps with any already existing ranges in the uid=>iface map*/
|
||||||
|
static int _resolv_check_uid_range_overlap_locked(int low, int high);
|
||||||
|
/* get a resolv_uidiface_info structure from _res_uidiface_list with a certain uid */
|
||||||
|
static struct resolv_uidiface_info* _get_uid_iface_info_locked(int uid);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_res_cache_init(void)
|
_res_cache_init(void)
|
||||||
{
|
{
|
||||||
@ -1852,8 +1871,10 @@ _res_cache_init(void)
|
|||||||
memset(&_res_default_ifname, 0, sizeof(_res_default_ifname));
|
memset(&_res_default_ifname, 0, sizeof(_res_default_ifname));
|
||||||
memset(&_res_cache_list, 0, sizeof(_res_cache_list));
|
memset(&_res_cache_list, 0, sizeof(_res_cache_list));
|
||||||
memset(&_res_pidiface_list, 0, sizeof(_res_pidiface_list));
|
memset(&_res_pidiface_list, 0, sizeof(_res_pidiface_list));
|
||||||
|
memset(&_res_uidiface_list, 0, sizeof(_res_uidiface_list));
|
||||||
pthread_mutex_init(&_res_cache_list_lock, NULL);
|
pthread_mutex_init(&_res_cache_list_lock, NULL);
|
||||||
pthread_mutex_init(&_res_pidiface_list_lock, NULL);
|
pthread_mutex_init(&_res_pidiface_list_lock, NULL);
|
||||||
|
pthread_mutex_init(&_res_uidiface_list_lock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct resolv_cache*
|
struct resolv_cache*
|
||||||
@ -2411,6 +2432,129 @@ _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_remove_uidiface_info_locked(int low, int high) {
|
||||||
|
struct resolv_uidiface_info* result = &_res_uidiface_list.next;
|
||||||
|
struct resolv_uidiface_info* prev = NULL;
|
||||||
|
|
||||||
|
while (result != NULL && result->low != low && result->high != high) {
|
||||||
|
prev = result;
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
if (prev != NULL && result != NULL) {
|
||||||
|
prev->next = result->next;
|
||||||
|
free(result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resolv_uidiface_info*
|
||||||
|
_get_uid_iface_info_locked(int uid)
|
||||||
|
{
|
||||||
|
struct resolv_uidiface_info* result = &_res_uidiface_list.next;
|
||||||
|
while (result != NULL && !(result->low <= uid && result->high >= uid)) {
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_resolv_check_uid_range_overlap_locked(int low, int high)
|
||||||
|
{
|
||||||
|
struct resolv_uidiface_info* cur = &_res_uidiface_list.next;
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->low <= high && cur->high >= low) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_resolv_set_iface_for_uid_range(const char* ifname, int low, int high)
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
struct resolv_uidiface_info* uidiface_info;
|
||||||
|
// make sure the uid iface list is created
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||||
|
//check that we aren't adding an overlapping range
|
||||||
|
if (!_resolv_check_uid_range_overlap_locked(low,high)) {
|
||||||
|
uidiface_info = calloc(sizeof(*uidiface_info), 1);
|
||||||
|
if (uidiface_info) {
|
||||||
|
uidiface_info->low = low;
|
||||||
|
uidiface_info->high = high;
|
||||||
|
int len = sizeof(uidiface_info->ifname);
|
||||||
|
strncpy(uidiface_info->ifname, ifname, len - 1);
|
||||||
|
uidiface_info->ifname[len - 1] = '\0';
|
||||||
|
|
||||||
|
uidiface_info->next = _res_uidiface_list.next;
|
||||||
|
_res_uidiface_list.next = uidiface_info;
|
||||||
|
|
||||||
|
XLOG("_resolv_set_iface_for_uid_range: [%d,%d], iface %s\n", low, high, ifname);
|
||||||
|
} else {
|
||||||
|
XLOG("_resolv_set_iface_for_uid_range failing calloc\n");
|
||||||
|
rv = -1;
|
||||||
|
errno = EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XLOG("_resolv_set_iface_for_uid_range range [%d,%d] overlaps\n", low, high);
|
||||||
|
rv = -1;
|
||||||
|
errno = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_resolv_clear_iface_for_uid_range(int low, int high)
|
||||||
|
{
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||||
|
|
||||||
|
int rv = _remove_uidiface_info_locked(low, high);
|
||||||
|
|
||||||
|
XLOG("_resolv_clear_iface_for_uid_range: low %d high %d\n", low, high);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_resolv_get_uids_associated_interface(int uid, char* buff, int buffLen)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (!buff) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||||
|
|
||||||
|
struct resolv_uidiface_info* uidiface_info = _get_uid_iface_info_locked(uid);
|
||||||
|
buff[0] = '\0';
|
||||||
|
if (uidiface_info) {
|
||||||
|
len = strlen(uidiface_info->ifname);
|
||||||
|
if (len < buffLen) {
|
||||||
|
strncpy(buff, uidiface_info->ifname, len);
|
||||||
|
buff[len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XLOG("_resolv_get_uids_associated_interface buff: %s\n", buff);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
_resolv_get_default_iface(char* buff, size_t buffLen)
|
_resolv_get_default_iface(char* buff, size_t buffLen)
|
||||||
{
|
{
|
||||||
|
@ -75,6 +75,24 @@ extern void _resolv_clear_iface_for_pid(int pid);
|
|||||||
* buffLen Length of buff. An interface is at most IF_NAMESIZE in length */
|
* buffLen Length of buff. An interface is at most IF_NAMESIZE in length */
|
||||||
extern int _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen);
|
extern int _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen);
|
||||||
|
|
||||||
|
|
||||||
|
/** set a uid range to use the name servers of the specified interface
|
||||||
|
* If [low,high] overlaps with an already existing rule -1 is returned */
|
||||||
|
extern int _resolv_set_iface_for_uid_range(const char* ifname, int low, int high);
|
||||||
|
|
||||||
|
/* clear a uid range from being associated with an interface
|
||||||
|
* If the range given is not mapped -1 is returned. */
|
||||||
|
extern int _resolv_clear_iface_for_uid_range(int low, int high);
|
||||||
|
|
||||||
|
/** Gets the name of the interface to which the uid is attached.
|
||||||
|
* On error, -1 is returned.
|
||||||
|
* If no interface is found, 0 is returned and buff is set to empty ('\0').
|
||||||
|
* If an interface is found, the name is copied to buff and the length of the name is returned.
|
||||||
|
* Arguments: uid The uid to find an interface for
|
||||||
|
* buff A buffer to copy the result to
|
||||||
|
* buffLen Length of buff. An interface is at most IF_NAMESIZE in length */
|
||||||
|
extern int _resolv_get_uids_associated_interface(int uid, char* buff, int buffLen);
|
||||||
|
|
||||||
#endif /* _BIONIC_RESOLV_IFACE_FUNCTIONS_DECLARED */
|
#endif /* _BIONIC_RESOLV_IFACE_FUNCTIONS_DECLARED */
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user