mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-04 08:15:21 +00:00
parser: add regex generator for range
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
committed by
John Johansen
parent
2be9c431ca
commit
a71ac76e6d
@@ -107,7 +107,7 @@ STATIC_HDRS = af_rule.h af_unix.h capability.h common_optarg.h dbus.h \
|
|||||||
file_cache.h immunix.h lib.h mount.h network.h parser.h \
|
file_cache.h immunix.h lib.h mount.h network.h parser.h \
|
||||||
parser_include.h parser_version.h policy_cache.h policydb.h \
|
parser_include.h parser_version.h policy_cache.h policydb.h \
|
||||||
profile.h ptrace.h rule.h signal.h userns.h mqueue.h io_uring.h \
|
profile.h ptrace.h rule.h signal.h userns.h mqueue.h io_uring.h \
|
||||||
common_flags.h
|
common_flags.h bignum.h
|
||||||
|
|
||||||
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_names.h
|
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_names.h
|
||||||
GENERATED_HDRS = af_names.h generated_af_names.h \
|
GENERATED_HDRS = af_names.h generated_af_names.h \
|
||||||
|
235
parser/bignum.h
Normal file
235
parser/bignum.h
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023
|
||||||
|
* Canonical Ltd. (All rights reserved)
|
||||||
|
*
|
||||||
|
* 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. or Canonical
|
||||||
|
* Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AA_BIGNUM_H
|
||||||
|
#define __AA_BIGNUM_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class bignum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
uint64_t sad = 543;
|
||||||
|
uint8_t base;
|
||||||
|
bool negative = false;
|
||||||
|
bignum () {}
|
||||||
|
|
||||||
|
bignum (unsigned long val) {
|
||||||
|
if (val == 0)
|
||||||
|
data.push_back(val);
|
||||||
|
else {
|
||||||
|
while(val > 0) {
|
||||||
|
data.push_back(val % 10);
|
||||||
|
val /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum (const char *val) {
|
||||||
|
while (*val) {
|
||||||
|
data.push_back(*val - 48);
|
||||||
|
val++;
|
||||||
|
}
|
||||||
|
std::reverse(data.begin(), data.end());
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum (const uint8_t val[16]) {
|
||||||
|
size_t i;
|
||||||
|
bool flag = true;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if ((val[i] & 0xF0) >> 4 != 0)
|
||||||
|
flag = false;
|
||||||
|
if (!flag)
|
||||||
|
data.push_back((val[i] & 0xF0) >> 4);
|
||||||
|
if ((val[i] & 0x0F) != 0)
|
||||||
|
flag = false;
|
||||||
|
if (!flag)
|
||||||
|
data.push_back(val[i] & 0x0F);
|
||||||
|
}
|
||||||
|
std::reverse(data.begin(), data.end());
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum operator+(const bignum &brhs) const {
|
||||||
|
bignum b1 = this->size() < brhs.size() ? *this : brhs;
|
||||||
|
bignum b2 = this->size() < brhs.size() ? brhs : *this;
|
||||||
|
bignum result;
|
||||||
|
result.base = this->base;
|
||||||
|
uint8_t carryover = 0;
|
||||||
|
uint8_t sum;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < b1.size(); i++) {
|
||||||
|
sum = b1[i] + b2[i] + carryover;
|
||||||
|
if (sum > base - 1)
|
||||||
|
carryover = 1;
|
||||||
|
else
|
||||||
|
carryover = 0;
|
||||||
|
result.data.push_back(sum % base);
|
||||||
|
}
|
||||||
|
for (; i < b2.size(); i++) {
|
||||||
|
sum = b2[i] + carryover;
|
||||||
|
if (sum > base - 1)
|
||||||
|
carryover = 1;
|
||||||
|
else
|
||||||
|
carryover = 0;
|
||||||
|
result.data.push_back(sum % base);
|
||||||
|
}
|
||||||
|
if (carryover != 0)
|
||||||
|
result.data.push_back(carryover);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum operator-(const bignum &brhs) const {
|
||||||
|
bignum b1 = this->size() < brhs.size() ? *this : brhs;
|
||||||
|
bignum b2 = this->size() < brhs.size() ? brhs : *this;
|
||||||
|
bignum result;
|
||||||
|
result.negative = *this < brhs;
|
||||||
|
result.base = this->base;
|
||||||
|
int8_t borrow = 0;
|
||||||
|
int8_t sub;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < b1.size(); i++) {
|
||||||
|
sub = b2[i] - b1[i] - borrow;
|
||||||
|
if (sub < 0) {
|
||||||
|
sub += base;
|
||||||
|
borrow = 1;
|
||||||
|
} else
|
||||||
|
borrow = 0;
|
||||||
|
result.data.push_back(sub);
|
||||||
|
}
|
||||||
|
for (; i < b2.size(); i++) {
|
||||||
|
sub = b2[i] - borrow;
|
||||||
|
if (sub < 0) {
|
||||||
|
sub += base;
|
||||||
|
borrow = 1;
|
||||||
|
} else
|
||||||
|
borrow = 0;
|
||||||
|
result.data.push_back(sub);
|
||||||
|
}
|
||||||
|
if (borrow) {
|
||||||
|
int8_t tmp = result.data[result.size() - 1] -= base;
|
||||||
|
tmp *= -1;
|
||||||
|
result.data[result.size() - 1] = tmp;
|
||||||
|
}
|
||||||
|
while (result.size() > 1 && result.data[result.size() - 1] == 0)
|
||||||
|
result.data.pop_back();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
bool operator>=(const bignum &rhs) const {
|
||||||
|
return cmp_bignum(this->data, rhs.data) >= 0;
|
||||||
|
}
|
||||||
|
bool operator<=(const bignum &rhs) const {
|
||||||
|
return cmp_bignum(this->data, rhs.data) <= 0;
|
||||||
|
}
|
||||||
|
bool operator>(const bignum &rhs) const {
|
||||||
|
return cmp_bignum(this->data, rhs.data) > 0;
|
||||||
|
}
|
||||||
|
bool operator<(const bignum &rhs) const {
|
||||||
|
return cmp_bignum(this->data, rhs.data) < 0;
|
||||||
|
}
|
||||||
|
int operator[](int index) const {
|
||||||
|
return this->data[index];
|
||||||
|
}
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, bignum &bn);
|
||||||
|
size_t size() const {
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns:
|
||||||
|
- 0, if the lhs and rhs are equal;
|
||||||
|
- a negative value if lhs is less than rhs;
|
||||||
|
- a positive value if lhs is greater than rhs.
|
||||||
|
*/
|
||||||
|
int cmp_bignum(std::vector<uint8_t> lhs, std::vector<uint8_t> rhs) const
|
||||||
|
{
|
||||||
|
if (lhs.size() > rhs.size())
|
||||||
|
return 1;
|
||||||
|
else if (lhs.size() < rhs.size())
|
||||||
|
return -1;
|
||||||
|
else {
|
||||||
|
/* assumes the digits are stored in reverse order */
|
||||||
|
std::reverse(lhs.begin(), lhs.end());
|
||||||
|
std::reverse(rhs.begin(), rhs.end());
|
||||||
|
for (size_t i = 0; i < lhs.size(); i++) {
|
||||||
|
if (lhs[i] > rhs[i])
|
||||||
|
return 1;
|
||||||
|
if (lhs[i] < rhs[i])
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bignum lower_bound_regex(bignum val)
|
||||||
|
{
|
||||||
|
/* single digit numbers reduce to 0 */
|
||||||
|
if (val.size() == 1) {
|
||||||
|
val.data[0] = 0;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& j : val.data) {
|
||||||
|
uint8_t tmp = j;
|
||||||
|
j = 0;
|
||||||
|
if (tmp != val.base - 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (&j == &val.data[val.size()-2]) {
|
||||||
|
val.data[val.size()-1] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bignum upper_bound_regex(bignum val)
|
||||||
|
{
|
||||||
|
for (auto& j : val.data) {
|
||||||
|
uint8_t tmp = j;
|
||||||
|
j = val.base - 1;
|
||||||
|
if (tmp != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &os, bignum &bn)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
bignum tmp = bn;
|
||||||
|
std::reverse(tmp.data.begin(), tmp.data.end());
|
||||||
|
for (auto i : tmp.data)
|
||||||
|
ss << std::hex << (int) i;
|
||||||
|
os << ss.str();
|
||||||
|
return os;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __AA_BIGNUM_H */
|
@@ -37,6 +37,7 @@
|
|||||||
#include "libapparmor_re/apparmor_re.h"
|
#include "libapparmor_re/apparmor_re.h"
|
||||||
#include "libapparmor_re/aare_rules.h"
|
#include "libapparmor_re/aare_rules.h"
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
|
#include "bignum.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -411,6 +412,7 @@ extern pattern_t convert_aaregex_to_pcre(const char *aare, int anchor, int glob,
|
|||||||
extern int build_list_val_expr(std::string& buffer, struct value_list *list);
|
extern int build_list_val_expr(std::string& buffer, struct value_list *list);
|
||||||
extern int convert_entry(std::string& buffer, char *entry);
|
extern int convert_entry(std::string& buffer, char *entry);
|
||||||
extern int clear_and_convert_entry(std::string& buffer, char *entry);
|
extern int clear_and_convert_entry(std::string& buffer, char *entry);
|
||||||
|
extern int convert_range(std::string& buffer, bignum start, bignum end);
|
||||||
extern int process_regex(Profile *prof);
|
extern int process_regex(Profile *prof);
|
||||||
extern int post_process_entry(struct cod_entry *entry);
|
extern int post_process_entry(struct cod_entry *entry);
|
||||||
|
|
||||||
|
@@ -845,6 +845,98 @@ int clear_and_convert_entry(std::string& buffer, char *entry)
|
|||||||
return convert_entry(buffer, entry);
|
return convert_entry(buffer, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<std::pair<bignum, bignum>> regex_range_generator(bignum start, bignum end)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<bignum, bignum>> forward;
|
||||||
|
std::vector<std::pair<bignum, bignum>> reverse;
|
||||||
|
bignum next, prev;
|
||||||
|
|
||||||
|
while (start <= end) {
|
||||||
|
next = bignum::upper_bound_regex(start);
|
||||||
|
if (next > end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
forward.emplace_back(start, next);
|
||||||
|
start = next + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!end.negative && end >= start) {
|
||||||
|
prev = bignum::lower_bound_regex(end);
|
||||||
|
if (prev < start || prev.negative)
|
||||||
|
break;
|
||||||
|
|
||||||
|
reverse.emplace_back(prev, end);
|
||||||
|
end = prev - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!end.negative && start <= end) {
|
||||||
|
forward.emplace_back(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
forward.insert(forward.end(), reverse.rbegin(), reverse.rend());
|
||||||
|
return forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string generate_regex_range(bignum start, bignum end)
|
||||||
|
{
|
||||||
|
std::ostringstream result;
|
||||||
|
std::vector<std::pair<bignum, bignum>> regex_range;
|
||||||
|
int j;
|
||||||
|
regex_range = regex_range_generator(start, end);
|
||||||
|
for (auto &i: regex_range) {
|
||||||
|
bignum sstart = i.first;
|
||||||
|
bignum send = i.second;
|
||||||
|
|
||||||
|
for (j = sstart.size() - 1; j >= 0; j--) {
|
||||||
|
if (sstart[j] == send[j]) {
|
||||||
|
result << std::hex << sstart[j];
|
||||||
|
} else {
|
||||||
|
if (sstart[j] < 10 && send[j] >= 10) {
|
||||||
|
result << '[';
|
||||||
|
result << std::hex << sstart[j];
|
||||||
|
if (sstart[j] < 9) {
|
||||||
|
result << '-';
|
||||||
|
result << '9';
|
||||||
|
}
|
||||||
|
if (send[j] > 10) {
|
||||||
|
result << 'a';
|
||||||
|
result << '-';
|
||||||
|
}
|
||||||
|
result << std::hex << send[j];
|
||||||
|
result << ']';
|
||||||
|
} else {
|
||||||
|
result << '[';
|
||||||
|
result << std::hex << sstart[j];
|
||||||
|
result << '-';
|
||||||
|
result << std::hex << send[j];
|
||||||
|
result << ']';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (&i != ®ex_range.back())
|
||||||
|
result << ",";
|
||||||
|
}
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
int convert_range(std::string& buffer, bignum start, bignum end)
|
||||||
|
{
|
||||||
|
pattern_t ptype;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
std::string regex_range = generate_regex_range(start, end);
|
||||||
|
|
||||||
|
if (!regex_range.empty()) {
|
||||||
|
ptype = convert_aaregex_to_pcre(regex_range.c_str(), 0, glob_default, buffer, &pos);
|
||||||
|
if (ptype == ePatternInvalid)
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
buffer.append(default_match_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int post_process_policydb_ents(Profile *prof)
|
int post_process_policydb_ents(Profile *prof)
|
||||||
{
|
{
|
||||||
for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++) {
|
for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++) {
|
||||||
|
Reference in New Issue
Block a user