mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser: add regex generator for range
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
parent
2be9c431ca
commit
a71ac76e6d
4 changed files with 330 additions and 1 deletions
|
@ -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 \
|
||||
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 \
|
||||
common_flags.h
|
||||
common_flags.h bignum.h
|
||||
|
||||
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_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/aare_rules.h"
|
||||
#include "rule.h"
|
||||
#include "bignum.h"
|
||||
|
||||
#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 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 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++) {
|
||||
|
|
Loading…
Add table
Reference in a new issue