2006-04-11 21:52:54 +00:00
|
|
|
/*
|
2007-04-11 08:12:51 +00:00
|
|
|
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
|
|
|
* NOVELL (All rights reserved)
|
2006-04-11 21:52:54 +00:00
|
|
|
*
|
2013-10-14 14:37:48 -07:00
|
|
|
* Copyright (c) 2013
|
|
|
|
* Canonical Ltd. (All rights reserved)
|
|
|
|
*
|
2006-04-11 21:52:54 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
|
|
* License published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, contact Novell, Inc.
|
|
|
|
*/
|
|
|
|
|
2007-06-26 21:09:46 +00:00
|
|
|
#include <assert.h>
|
2006-04-11 21:52:54 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
2015-03-25 17:09:27 -05:00
|
|
|
#include <sys/apparmor.h>
|
2014-04-23 11:07:01 -07:00
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
#include "lib.h"
|
2006-04-11 21:52:54 +00:00
|
|
|
#include "parser.h"
|
2013-09-27 16:16:37 -07:00
|
|
|
#include "profile.h"
|
2007-02-27 02:29:16 +00:00
|
|
|
#include "libapparmor_re/apparmor_re.h"
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/unistd.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define SD_CODE_SIZE (sizeof(u8))
|
|
|
|
#define SD_STR_LEN (sizeof(u16))
|
|
|
|
|
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
int __sd_serialize_profile(int option, aa_kernel_interface *kernel_interface,
|
|
|
|
Profile *prof, int cache_fd);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
static void print_error(int error)
|
|
|
|
{
|
|
|
|
switch (error) {
|
|
|
|
case -ESPIPE:
|
|
|
|
PERROR(_("Bad write position\n"));
|
|
|
|
break;
|
|
|
|
case -EPERM:
|
|
|
|
PERROR(_("Permission denied\n"));
|
|
|
|
break;
|
|
|
|
case -ENOMEM:
|
|
|
|
PERROR(_("Out of memory\n"));
|
|
|
|
break;
|
|
|
|
case -EFAULT:
|
2011-01-14 17:44:51 -06:00
|
|
|
PERROR(_("Couldn't copy profile: Bad memory address\n"));
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
case -EPROTO:
|
|
|
|
PERROR(_("Profile doesn't conform to protocol\n"));
|
|
|
|
break;
|
|
|
|
case -EBADMSG:
|
|
|
|
PERROR(_("Profile does not match signature\n"));
|
|
|
|
break;
|
|
|
|
case -EPROTONOSUPPORT:
|
2006-08-04 17:22:19 +00:00
|
|
|
PERROR(_("Profile version not supported by Apparmor module\n"));
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
case -EEXIST:
|
|
|
|
PERROR(_("Profile already exists\n"));
|
|
|
|
break;
|
|
|
|
case -ENOENT:
|
|
|
|
PERROR(_("Profile doesn't exist\n"));
|
|
|
|
break;
|
2009-03-13 03:44:26 +00:00
|
|
|
case -EACCES:
|
|
|
|
PERROR(_("Permission denied; attempted to load a profile while confined?\n"));
|
|
|
|
break;
|
2006-04-11 21:52:54 +00:00
|
|
|
default:
|
2009-03-13 03:44:26 +00:00
|
|
|
PERROR(_("Unknown error (%d): %s\n"), -error, strerror(-error));
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
int load_profile(int option, aa_kernel_interface *kernel_interface,
|
|
|
|
Profile *prof, int cache_fd)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
int error = 0;
|
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
PDEBUG("Serializing policy for %s.\n", prof->name);
|
2015-03-25 17:09:26 -05:00
|
|
|
retval = __sd_serialize_profile(option, kernel_interface, prof, cache_fd);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
if (retval < 0) {
|
|
|
|
error = retval; /* yeah, we'll just report the last error */
|
|
|
|
switch (option) {
|
|
|
|
case OPTION_ADD:
|
|
|
|
PERROR(_("%s: Unable to add \"%s\". "),
|
2013-09-27 16:16:37 -07:00
|
|
|
progname, prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
print_error(error);
|
|
|
|
break;
|
|
|
|
case OPTION_REPLACE:
|
|
|
|
PERROR(_("%s: Unable to replace \"%s\". "),
|
2013-09-27 16:16:37 -07:00
|
|
|
progname, prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
print_error(error);
|
|
|
|
break;
|
|
|
|
case OPTION_REMOVE:
|
|
|
|
PERROR(_("%s: Unable to remove \"%s\". "),
|
2013-09-27 16:16:37 -07:00
|
|
|
progname, prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
print_error(error);
|
|
|
|
break;
|
|
|
|
case OPTION_STDOUT:
|
|
|
|
PERROR(_("%s: Unable to write to stdout\n"),
|
|
|
|
progname);
|
|
|
|
break;
|
2010-06-26 13:13:52 -07:00
|
|
|
case OPTION_OFILE:
|
|
|
|
PERROR(_("%s: Unable to write to output file\n"),
|
|
|
|
progname);
|
2018-07-13 15:21:24 +02:00
|
|
|
break;
|
2006-04-11 21:52:54 +00:00
|
|
|
default:
|
|
|
|
PERROR(_("%s: ASSERT: Invalid option: %d\n"),
|
|
|
|
progname, option);
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-11 10:56:04 -08:00
|
|
|
} else if (conf_verbose) {
|
2006-04-11 21:52:54 +00:00
|
|
|
switch (option) {
|
|
|
|
case OPTION_ADD:
|
|
|
|
printf(_("Addition succeeded for \"%s\".\n"),
|
2013-09-27 16:16:37 -07:00
|
|
|
prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
case OPTION_REPLACE:
|
|
|
|
printf(_("Replacement succeeded for \"%s\".\n"),
|
2013-09-27 16:16:37 -07:00
|
|
|
prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
case OPTION_REMOVE:
|
|
|
|
printf(_("Removal succeeded for \"%s\".\n"),
|
2013-09-27 16:16:37 -07:00
|
|
|
prof->name);
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
case OPTION_STDOUT:
|
2010-06-26 13:13:52 -07:00
|
|
|
case OPTION_OFILE:
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
PERROR(_("%s: ASSERT: Invalid option: %d\n"),
|
|
|
|
progname, option);
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum sd_code {
|
|
|
|
SD_U8,
|
|
|
|
SD_U16,
|
|
|
|
SD_U32,
|
|
|
|
SD_U64,
|
|
|
|
SD_NAME, /* same as string except it is items name */
|
|
|
|
SD_STRING,
|
|
|
|
SD_BLOB,
|
|
|
|
SD_STRUCT,
|
|
|
|
SD_STRUCTEND,
|
|
|
|
SD_LIST,
|
|
|
|
SD_LISTEND,
|
2007-07-27 20:29:47 +00:00
|
|
|
SD_ARRAY,
|
|
|
|
SD_ARRAYEND,
|
2006-04-11 21:52:54 +00:00
|
|
|
SD_OFFSET
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *sd_code_names[] = {
|
|
|
|
"SD_U8",
|
|
|
|
"SD_U16",
|
|
|
|
"SD_U32",
|
|
|
|
"SD_U64",
|
|
|
|
"SD_NAME",
|
|
|
|
"SD_STRING",
|
|
|
|
"SD_BLOB",
|
|
|
|
"SD_STRUCT",
|
|
|
|
"SD_STRUCTEND",
|
|
|
|
"SD_LIST",
|
|
|
|
"SD_LISTEND",
|
2008-04-06 18:55:46 +00:00
|
|
|
"SD_ARRAY",
|
|
|
|
"SD_ARRAYEND",
|
2006-04-11 21:52:54 +00:00
|
|
|
"SD_OFFSET"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write8(std::ostringstream &buf, u8 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
buf.write((const char *) &b, 1);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write16(std::ostringstream &buf, u16 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
u16 tmp;
|
|
|
|
tmp = cpu_to_le16(b);
|
|
|
|
buf.write((const char *) &tmp, 2);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write32(std::ostringstream &buf, u32 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
u32 tmp;
|
|
|
|
tmp = cpu_to_le32(b);
|
|
|
|
buf.write((const char *) &tmp, 4);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write64(std::ostringstream &buf, u64 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
u64 tmp;
|
|
|
|
tmp = cpu_to_le64(b);
|
|
|
|
buf.write((const char *) &tmp, 8);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_uint8(std::ostringstream &buf, u8 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_U8);
|
|
|
|
sd_write8(buf, b);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_uint16(std::ostringstream &buf, u16 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_U16);
|
|
|
|
sd_write16(buf, b);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_uint32(std::ostringstream &buf, u32 b)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_U32);
|
|
|
|
sd_write32(buf, b);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_uint64(std::ostringstream &buf, u64 b)
|
2008-04-06 18:55:46 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_U64);
|
|
|
|
sd_write64(buf, b);
|
2008-04-06 18:55:46 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_name(std::ostringstream &buf, const char *name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
|
|
|
PDEBUG("Writing name '%s'\n", name);
|
|
|
|
if (name) {
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_NAME);
|
|
|
|
sd_write16(buf, strlen(name) + 1);
|
|
|
|
buf.write(name, strlen(name) + 1);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_blob(std::ostringstream &buf, void *b, int buf_size, char *name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
sd_write8(buf, SD_BLOB);
|
|
|
|
sd_write32(buf, buf_size);
|
|
|
|
buf.write((const char *) b, buf_size);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
|
|
|
|
static char zeros[64];
|
2014-01-09 17:09:54 -08:00
|
|
|
#define align64(X) (((X) + (typeof(X)) 7) & ~((typeof(X)) 7))
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_aligned_blob(std::ostringstream &buf, void *b, int b_size,
|
2013-10-01 10:59:04 -07:00
|
|
|
const char *name)
|
2007-02-27 02:29:16 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
/* pad calculation MUST come after name is written */
|
|
|
|
size_t pad = align64(buf.tellp() + ((std::streamoff) 5l)) - (buf.tellp() + ((std::streamoff) 5l));
|
|
|
|
sd_write8(buf, SD_BLOB);
|
|
|
|
sd_write32(buf, b_size + pad);
|
|
|
|
buf.write(zeros, pad);
|
|
|
|
buf.write((const char *) b, b_size);
|
2007-02-27 02:29:16 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
static void sd_write_strn(std::ostringstream &buf, char *b, int size, const char *name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
sd_write8(buf, SD_STRING);
|
|
|
|
sd_write16(buf, size);
|
|
|
|
buf.write(b, size);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_string(std::ostringstream &buf, char *b, const char *name)
|
2008-04-16 04:45:02 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_strn(buf, b, strlen(b) + 1, name);
|
2008-04-16 04:45:02 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_struct(std::ostringstream &buf, const char *name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
sd_write8(buf, SD_STRUCT);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_structend(std::ostringstream &buf)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_STRUCTEND);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_array(std::ostringstream &buf, const char *name, int size)
|
2007-07-27 20:29:47 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
sd_write8(buf, SD_ARRAY);
|
|
|
|
sd_write16(buf, size);
|
2007-07-27 20:29:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_arrayend(std::ostringstream &buf)
|
2007-07-27 20:29:47 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_ARRAYEND);
|
2007-07-27 20:29:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_list(std::ostringstream &buf, const char *name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, name);
|
|
|
|
sd_write8(buf, SD_LIST);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 17:40:30 -07:00
|
|
|
static inline void sd_write_listend(std::ostringstream &buf)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write8(buf, SD_LISTEND);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
void sd_serialize_dfa(std::ostringstream &buf, void *dfa, size_t size)
|
2007-02-27 02:29:16 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
if (dfa)
|
|
|
|
sd_write_aligned_blob(buf, dfa, size, "aadfa");
|
2007-02-27 02:29:16 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
void sd_serialize_rlimits(std::ostringstream &buf, struct aa_rlimits *limits)
|
2008-04-06 18:55:46 +00:00
|
|
|
{
|
|
|
|
if (!limits->specified)
|
2014-04-23 11:07:01 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
sd_write_struct(buf, "rlimits");
|
|
|
|
sd_write_uint32(buf, limits->specified);
|
|
|
|
sd_write_array(buf, NULL, RLIM_NLIMITS);
|
|
|
|
for (int i = 0; i < RLIM_NLIMITS; i++) {
|
|
|
|
sd_write_uint64(buf, limits->limits[i]);
|
2008-04-06 18:55:46 +00:00
|
|
|
}
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_arrayend(buf);
|
|
|
|
sd_write_structend(buf);
|
2008-04-06 18:55:46 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
void sd_serialize_xtable(std::ostringstream &buf, char **table)
|
2008-04-16 04:45:02 +00:00
|
|
|
{
|
2014-04-23 11:07:01 -07:00
|
|
|
int count;
|
2008-04-16 04:45:02 +00:00
|
|
|
if (!table[4])
|
2014-04-23 11:07:01 -07:00
|
|
|
return;
|
|
|
|
sd_write_struct(buf, "xtable");
|
2008-04-16 04:45:02 +00:00
|
|
|
count = 0;
|
2014-04-23 11:07:01 -07:00
|
|
|
for (int i = 4; i < AA_EXEC_COUNT; i++) {
|
2008-04-16 04:45:02 +00:00
|
|
|
if (table[i])
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_array(buf, NULL, count);
|
|
|
|
for (int i = 4; i < count + 4; i++) {
|
2008-04-16 04:45:02 +00:00
|
|
|
int len = strlen(table[i]) + 1;
|
|
|
|
|
|
|
|
/* if its a namespace make sure the second : is overwritten
|
|
|
|
* with 0, so that the namespace and name are \0 seperated
|
|
|
|
*/
|
|
|
|
if (*table[i] == ':') {
|
|
|
|
char *tmp = table[i] + 1;
|
|
|
|
strsep(&tmp, ":");
|
|
|
|
}
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_strn(buf, table[i], len, NULL);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_arrayend(buf);
|
|
|
|
sd_write_structend(buf);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
|
2007-06-26 21:09:46 +00:00
|
|
|
int flattened)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2009-08-20 15:27:12 +00:00
|
|
|
uint64_t allowed_caps;
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_struct(buf, "profile");
|
2007-06-26 21:09:46 +00:00
|
|
|
if (flattened) {
|
|
|
|
assert(profile->parent);
|
2015-03-25 17:09:26 -05:00
|
|
|
autofree char *name = (char *) malloc(3 + strlen(profile->name) + strlen(profile->parent->name));
|
2007-06-26 21:09:46 +00:00
|
|
|
if (!name)
|
2014-04-23 11:07:01 -07:00
|
|
|
return;
|
2007-06-26 21:09:46 +00:00
|
|
|
sprintf(name, "%s//%s", profile->parent->name, profile->name);
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_string(buf, name, NULL);
|
2007-06-26 21:09:46 +00:00
|
|
|
} else {
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_string(buf, profile->name, NULL);
|
2007-06-26 21:09:46 +00:00
|
|
|
}
|
2009-07-30 06:09:19 +00:00
|
|
|
|
2009-11-11 10:56:04 -08:00
|
|
|
/* only emit this if current kernel at least supports "create" */
|
|
|
|
if (perms_create) {
|
2013-09-27 16:11:00 -07:00
|
|
|
if (profile->xmatch) {
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_serialize_dfa(buf, profile->xmatch, profile->xmatch_size);
|
|
|
|
sd_write_uint32(buf, profile->xmatch_len);
|
2009-11-11 10:56:04 -08:00
|
|
|
}
|
2009-07-30 06:09:19 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_struct(buf, "flags");
|
2006-04-11 21:52:54 +00:00
|
|
|
/* used to be flags.debug, but that's no longer supported */
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_uint32(buf, profile->flags.hat);
|
|
|
|
sd_write_uint32(buf, profile->flags.complain);
|
|
|
|
sd_write_uint32(buf, profile->flags.audit);
|
|
|
|
sd_write_structend(buf);
|
2010-02-17 12:21:52 -08:00
|
|
|
if (profile->flags.path) {
|
|
|
|
int flags = 0;
|
|
|
|
if (profile->flags.path & PATH_CHROOT_REL)
|
|
|
|
flags |= 0x8;
|
|
|
|
if (profile->flags.path & PATH_MEDIATE_DELETED)
|
|
|
|
flags |= 0x10000;
|
|
|
|
if (profile->flags.path & PATH_ATTACH)
|
|
|
|
flags |= 0x4;
|
|
|
|
if (profile->flags.path & PATH_CHROOT_NSATTACH)
|
|
|
|
flags |= 0x10;
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, "path_flags");
|
|
|
|
sd_write_uint32(buf, flags);
|
2010-02-17 12:21:52 -08:00
|
|
|
}
|
2009-08-20 15:27:12 +00:00
|
|
|
|
|
|
|
#define low_caps(X) ((u32) ((X) & 0xffffffff))
|
|
|
|
#define high_caps(X) ((u32) (((X) >> 32) & 0xffffffff))
|
2013-09-27 16:16:37 -07:00
|
|
|
allowed_caps = (profile->caps.allow) & ~profile->caps.deny;
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_uint32(buf, low_caps(allowed_caps));
|
|
|
|
sd_write_uint32(buf, low_caps(allowed_caps & profile->caps.audit));
|
|
|
|
sd_write_uint32(buf, low_caps(profile->caps.deny & profile->caps.quiet));
|
|
|
|
sd_write_uint32(buf, 0);
|
|
|
|
|
|
|
|
sd_write_struct(buf, "caps64");
|
|
|
|
sd_write_uint32(buf, high_caps(allowed_caps));
|
|
|
|
sd_write_uint32(buf, high_caps(allowed_caps & profile->caps.audit));
|
|
|
|
sd_write_uint32(buf, high_caps(profile->caps.deny & profile->caps.quiet));
|
|
|
|
sd_write_uint32(buf, 0);
|
|
|
|
sd_write_structend(buf);
|
|
|
|
|
|
|
|
sd_serialize_rlimits(buf, &profile->rlimits);
|
2008-04-06 18:55:46 +00:00
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
if (profile->net.allow && kernel_supports_network) {
|
2009-07-24 17:24:41 +00:00
|
|
|
size_t i;
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_array(buf, "net_allowed_af", get_af_max());
|
2009-07-24 17:24:41 +00:00
|
|
|
for (i = 0; i < get_af_max(); i++) {
|
2014-04-23 11:07:01 -07:00
|
|
|
u16 allowed = profile->net.allow[i] &
|
|
|
|
~profile->net.deny[i];
|
|
|
|
sd_write_uint16(buf, allowed);
|
|
|
|
sd_write_uint16(buf, allowed & profile->net.audit[i]);
|
|
|
|
sd_write_uint16(buf, profile->net.deny[i] & profile->net.quiet[i]);
|
2007-07-27 20:29:47 +00:00
|
|
|
}
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_arrayend(buf);
|
2014-10-08 13:20:20 -07:00
|
|
|
} else if (profile->net.allow && (warnflags & WARN_RULE_NOT_ENFORCED))
|
2010-08-26 10:37:46 -07:00
|
|
|
pwarn(_("profile %s network rules not enforced\n"), profile->name);
|
2007-07-27 20:29:47 +00:00
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
if (profile->policy.dfa) {
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_struct(buf, "policydb");
|
|
|
|
sd_serialize_dfa(buf, profile->policy.dfa, profile->policy.size);
|
|
|
|
sd_write_structend(buf);
|
2012-02-16 08:14:46 -08:00
|
|
|
}
|
|
|
|
|
2007-02-27 02:29:16 +00:00
|
|
|
/* either have a single dfa or lists of different entry types */
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_serialize_dfa(buf, profile->dfa.dfa, profile->dfa.size);
|
|
|
|
sd_serialize_xtable(buf, profile->exec_table);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_structend(buf);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
void sd_serialize_top_profile(std::ostringstream &buf, Profile *profile)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2014-04-23 11:00:32 -07:00
|
|
|
uint32_t version;
|
2007-02-27 02:29:16 +00:00
|
|
|
|
2014-04-23 11:00:32 -07:00
|
|
|
version = ENCODE_VERSION(force_complain, policy_version,
|
|
|
|
parser_abi_version, kernel_abi_version);
|
2007-02-27 02:29:16 +00:00
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_name(buf, "version");
|
|
|
|
sd_write_uint32(buf, version);
|
2007-11-16 09:18:48 +00:00
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
if (profile->ns) {
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_write_string(buf, profile->ns, "namespace");
|
2007-11-16 09:18:48 +00:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_serialize_profile(buf, profile, profile->parent ? 1 : 0);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
int __sd_serialize_profile(int option, aa_kernel_interface *kernel_interface,
|
|
|
|
Profile *prof, int cache_fd)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2015-03-25 17:09:26 -05:00
|
|
|
autoclose int fd = -1;
|
2015-03-25 17:09:26 -05:00
|
|
|
int error, size, wsize;
|
2014-04-23 11:07:01 -07:00
|
|
|
std::ostringstream work_area;
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
switch (option) {
|
|
|
|
case OPTION_ADD:
|
|
|
|
case OPTION_REPLACE:
|
|
|
|
case OPTION_REMOVE:
|
|
|
|
break;
|
|
|
|
case OPTION_STDOUT:
|
|
|
|
fd = dup(1);
|
2015-03-25 17:09:26 -05:00
|
|
|
if (fd < 0) {
|
|
|
|
error = -errno;
|
|
|
|
PERROR(_("Unable to open stdout - %s\n"),
|
|
|
|
strerror(errno));
|
|
|
|
goto exit;
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
break;
|
2010-06-26 13:13:52 -07:00
|
|
|
case OPTION_OFILE:
|
|
|
|
fd = dup(fileno(ofile));
|
2015-03-25 17:09:26 -05:00
|
|
|
if (fd < 0) {
|
|
|
|
error = -errno;
|
|
|
|
PERROR(_("Unable to open output file - %s\n"),
|
|
|
|
strerror(errno));
|
|
|
|
goto exit;
|
|
|
|
}
|
2010-06-26 13:13:52 -07:00
|
|
|
break;
|
2006-04-11 21:52:54 +00:00
|
|
|
default:
|
|
|
|
error = -EINVAL;
|
|
|
|
goto exit;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-07-24 23:47:46 +00:00
|
|
|
error = 0;
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
if (option == OPTION_REMOVE) {
|
2009-11-11 10:56:04 -08:00
|
|
|
if (kernel_load) {
|
2015-03-25 17:09:26 -05:00
|
|
|
if (aa_kernel_interface_remove_policy(kernel_interface,
|
|
|
|
prof->fqname().c_str()) == -1)
|
2009-11-11 10:56:04 -08:00
|
|
|
error = -errno;
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
} else {
|
2015-03-25 17:09:26 -05:00
|
|
|
std::string tmp;
|
|
|
|
|
2014-04-23 11:07:01 -07:00
|
|
|
sd_serialize_top_profile(work_area, prof);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
tmp = work_area.str();
|
2014-04-23 11:07:01 -07:00
|
|
|
size = (long) work_area.tellp();
|
2015-03-25 17:09:26 -05:00
|
|
|
if (kernel_load) {
|
|
|
|
if (option == OPTION_ADD &&
|
2015-03-25 17:09:26 -05:00
|
|
|
aa_kernel_interface_load_policy(kernel_interface,
|
|
|
|
tmp.c_str(), size) == -1) {
|
2015-03-25 17:09:26 -05:00
|
|
|
error = -errno;
|
|
|
|
} else if (option == OPTION_REPLACE &&
|
2015-03-25 17:09:26 -05:00
|
|
|
aa_kernel_interface_replace_policy(kernel_interface,
|
|
|
|
tmp.c_str(), size) == -1) {
|
2009-11-11 10:56:04 -08:00
|
|
|
error = -errno;
|
|
|
|
}
|
2015-03-25 17:09:26 -05:00
|
|
|
} else if ((option == OPTION_STDOUT || option == OPTION_OFILE) &&
|
|
|
|
aa_kernel_interface_write_policy(fd, tmp.c_str(), size) == -1) {
|
|
|
|
error = -errno;
|
2009-07-24 07:36:09 +00:00
|
|
|
}
|
2015-03-25 17:09:26 -05:00
|
|
|
|
2009-07-24 07:36:09 +00:00
|
|
|
if (cache_fd != -1) {
|
2014-04-23 11:07:01 -07:00
|
|
|
wsize = write(cache_fd, tmp.c_str(), size);
|
2009-07-24 07:36:09 +00:00
|
|
|
if (wsize < 0) {
|
|
|
|
error = -errno;
|
|
|
|
} else if (wsize < size) {
|
|
|
|
PERROR(_("%s: Unable to write entire profile entry to cache\n"),
|
|
|
|
progname);
|
|
|
|
error = -EIO;
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
if (!prof->hat_table.empty() && option != OPTION_REMOVE) {
|
2015-03-25 17:09:26 -05:00
|
|
|
if (load_flattened_hats(prof, option, kernel_interface, cache_fd) == 0)
|
2007-06-26 21:09:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
exit:
|
|
|
|
return error;
|
|
|
|
}
|
2008-06-09 10:00:28 +00:00
|
|
|
|