mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-03 07:45:50 +00:00
Merge from trunk revs 1676 and 1677: Override AF_MAX for kernels that
don't support proper masking. Older versions of the apparmor kernel patches didn't handle receiving network tables of a larger size than expected. Allow the parser to detect the kernel version and override the AF_MAX value for those kernels. This also replaces the hack using a hardcoded limit of 36 for kernels missing the features flag. Also, ensure that the buffer read from /proc/sys/kernel/osrelease is null terminated. Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-By: Steve Beattie <sbeattie@ubuntu.com>
This commit is contained in:
@@ -176,6 +176,7 @@ struct var_string {
|
|||||||
#define FLAG_CHANGEHAT_1_4 2
|
#define FLAG_CHANGEHAT_1_4 2
|
||||||
#define FLAG_CHANGEHAT_1_5 3
|
#define FLAG_CHANGEHAT_1_5 3
|
||||||
extern int kernel_supports_network;
|
extern int kernel_supports_network;
|
||||||
|
extern int net_af_max_override;
|
||||||
extern int flag_changehat_version;
|
extern int flag_changehat_version;
|
||||||
extern int read_implies_exec;
|
extern int read_implies_exec;
|
||||||
extern dfaflags_t dfaflags;
|
extern dfaflags_t dfaflags;
|
||||||
|
@@ -87,6 +87,7 @@ char *flags_string = NULL;
|
|||||||
int regex_type = AARE_DFA;
|
int regex_type = AARE_DFA;
|
||||||
int perms_create = 0; /* perms contain create flag */
|
int perms_create = 0; /* perms contain create flag */
|
||||||
int kernel_supports_network = 1; /* kernel supports network rules */
|
int kernel_supports_network = 1; /* kernel supports network rules */
|
||||||
|
int net_af_max_override = -1; /* use kernel to determine af_max */
|
||||||
char *profile_namespace = NULL;
|
char *profile_namespace = NULL;
|
||||||
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
|
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
|
||||||
|
|
||||||
|
@@ -29,6 +29,10 @@
|
|||||||
#include <linux/socket.h>
|
#include <linux/socket.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "parser_yacc.h"
|
#include "parser_yacc.h"
|
||||||
@@ -236,6 +240,69 @@ static struct network_tuple network_mappings[] = {
|
|||||||
{NULL, 0, NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* The apparmor kernel patches up until 2.6.38 didn't handle networking
|
||||||
|
* tables with sizes > AF_MAX correctly. This could happen when the
|
||||||
|
* parser was built against newer kernel headers and then used to load
|
||||||
|
* policy on an older kernel. This could happen during upgrades or
|
||||||
|
* in multi-kernel boot systems.
|
||||||
|
*
|
||||||
|
* Try to detect the running kernel version and use that to determine
|
||||||
|
* AF_MAX
|
||||||
|
*/
|
||||||
|
#define PROC_VERSION "/proc/sys/kernel/osrelease"
|
||||||
|
static size_t kernel_af_max(void) {
|
||||||
|
char buffer[32];
|
||||||
|
int major;
|
||||||
|
int fd, res;
|
||||||
|
|
||||||
|
if (!net_af_max_override) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* the override parameter is specifying the max value */
|
||||||
|
if (net_af_max_override > 0)
|
||||||
|
return net_af_max_override;
|
||||||
|
|
||||||
|
fd = open(PROC_VERSION, O_RDONLY);
|
||||||
|
if (!fd)
|
||||||
|
/* fall back to default provided during build */
|
||||||
|
return 0;
|
||||||
|
res = read(fd, &buffer, sizeof(buffer));
|
||||||
|
close(fd);
|
||||||
|
if (!res)
|
||||||
|
return 0;
|
||||||
|
buffer[sizeof(buffer)-1] = '\0';
|
||||||
|
res = sscanf(buffer, "2.6.%d", &major);
|
||||||
|
if (res != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch(major) {
|
||||||
|
case 24:
|
||||||
|
case 25:
|
||||||
|
case 26:
|
||||||
|
return 34;
|
||||||
|
case 27:
|
||||||
|
return 35;
|
||||||
|
case 28:
|
||||||
|
case 29:
|
||||||
|
case 30:
|
||||||
|
return 36;
|
||||||
|
case 31:
|
||||||
|
case 32:
|
||||||
|
case 33:
|
||||||
|
case 34:
|
||||||
|
case 35:
|
||||||
|
return 37;
|
||||||
|
case 36:
|
||||||
|
case 37:
|
||||||
|
return 38;
|
||||||
|
/* kernels .38 and later should handle this correctly so no
|
||||||
|
* static mapping needed
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Yuck. We grab AF_* values to define above from linux/socket.h because
|
/* Yuck. We grab AF_* values to define above from linux/socket.h because
|
||||||
* they are more accurate than sys/socket.h for what the kernel actually
|
* they are more accurate than sys/socket.h for what the kernel actually
|
||||||
* supports. However, we can't just include linux/socket.h directly,
|
* supports. However, we can't just include linux/socket.h directly,
|
||||||
@@ -246,13 +313,29 @@ static struct network_tuple network_mappings[] = {
|
|||||||
* hence the wrapping function.
|
* hence the wrapping function.
|
||||||
*/
|
*/
|
||||||
size_t get_af_max() {
|
size_t get_af_max() {
|
||||||
|
size_t af_max;
|
||||||
/* HACK: declare that version without "create" had a static AF_MAX */
|
/* HACK: declare that version without "create" had a static AF_MAX */
|
||||||
if (!perms_create) return 36;
|
if (!perms_create && !net_af_max_override)
|
||||||
|
net_af_max_override = -1;
|
||||||
|
|
||||||
#if AA_AF_MAX > AF_MAX
|
#if AA_AF_MAX > AF_MAX
|
||||||
return AA_AF_MAX;
|
af_max = AA_AF_MAX;
|
||||||
#else
|
#else
|
||||||
return AF_MAX;
|
af_max = AF_MAX;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* HACK: some kernels didn't handle network tables from parsers
|
||||||
|
* compiled against newer kernel headers as they are larger than
|
||||||
|
* the running kernel expected. If net_override is defined check
|
||||||
|
* to see if there is a static max specified for that kernel
|
||||||
|
*/
|
||||||
|
if (net_af_max_override) {
|
||||||
|
size_t max = kernel_af_max();
|
||||||
|
if (max && max < af_max)
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return af_max;
|
||||||
}
|
}
|
||||||
struct aa_network_entry *new_network_ent(unsigned int family,
|
struct aa_network_entry *new_network_ent(unsigned int family,
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
|
Reference in New Issue
Block a user