147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <unistd.h>
247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <fcntl.h>
347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <string.h>
447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdlib.h>
547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h>
647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/socket.h>
747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "selinux_internal.h"
847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "policy.h"
947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#ifndef SO_PEERSEC
1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define SO_PEERSEC 31
1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#endif
1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint getpeercon(int fd, char ** context)
1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char *buf;
1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	socklen_t size;
1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	ssize_t ret;
1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	size = INITCONTEXTLEN + 1;
2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	buf = malloc(size);
2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (!buf)
2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		return -1;
2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	memset(buf, 0, size);
2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size);
2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (ret < 0 && errno == ERANGE) {
2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		char *newbuf;
2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		newbuf = realloc(buf, size);
3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (!newbuf)
3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			goto out;
3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		buf = newbuf;
3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		memset(buf, 0, size);
3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size);
3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner      out:
3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (ret < 0)
4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		free(buf);
4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	else
4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		*context = buf;
4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return ret;
4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
46