Projects STRLCPY ebpfguard Commits dc6c68d1
🤬
  • ebpf: Refactor `file_open` function

    * Split it into multiple functions.
    * Provide `Mode` and `Action` enums (for the whole crate).
  • Loading...
  • Michal Rostecki committed with vadorovsky 1 year ago
    dc6c68d1
    1 parent 78c44dea
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    guardity-ebpf/src/file_open.rs
    1  -use aya_bpf::{cty::c_long, programs::LsmContext, BpfContext};
    2  -use guardity_common::{AlertFileOpen, MAX_PATHS};
     1 +use aya_bpf::{maps::HashMap, programs::LsmContext, BpfContext};
     2 +use guardity_common::{AlertFileOpen, Paths, MAX_PATHS};
    3 3   
    4 4  use crate::{
    5 5   binprm::current_binprm_inode,
    6 6   consts::INODE_WILDCARD,
    7 7   maps::{ALERT_FILE_OPEN, ALLOWED_FILE_OPEN, DENIED_FILE_OPEN},
    8  - // maps::{ALERT_FILE_OPEN, ALLOWED_FILE_OPEN, DENIED_FILE_OPEN},
    9 8   vmlinux::file,
     9 + Action, Mode,
    10 10  };
    11 11   
    12 12  const MAX_DIR_DEPTH: usize = 16;
    skipped 12 lines
    25 25  ///
    26 26  /// #[lsm(name = "my_program")]
    27 27  /// pub fn my_program(ctx: LsmContext) -> i32 {
    28  -/// match file_open::file_open(ctx) {
    29  -/// Ok(ret) => ret,
    30  -/// Err(_) => 0,
    31  -/// }
     28 +/// file_open::file_open(ctx).into()
    32 29  /// }
    33 30  /// ```
    34  -pub fn file_open(ctx: LsmContext) -> Result<i32, c_long> {
     31 +pub fn file_open(ctx: LsmContext) -> Action {
    35 32   let file: *const file = unsafe { ctx.arg(0) };
    36 33   
    37 34   let binprm_inode = current_binprm_inode();
    skipped 1 lines
    39 36   
    40 37   if let Some(paths) = unsafe { ALLOWED_FILE_OPEN.get(&INODE_WILDCARD) } {
    41 38   if paths.paths[0] == 0 {
    42  - if let Some(paths) = unsafe { DENIED_FILE_OPEN.get(&INODE_WILDCARD) } {
    43  - if paths.paths[0] == 0 {
    44  - ALERT_FILE_OPEN.output(
    45  - &ctx,
    46  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    47  - 0,
    48  - );
    49  - return Ok(-1);
    50  - }
     39 + return check_conditions_and_alert(
     40 + &ctx,
     41 + &DENIED_FILE_OPEN,
     42 + file,
     43 + inode,
     44 + binprm_inode,
     45 + Mode::Denylist,
     46 + );
     47 + }
     48 + }
    51 49   
    52  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    53  - ALERT_FILE_OPEN.output(
    54  - &ctx,
    55  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    56  - 0,
    57  - );
    58  - return Ok(-1);
    59  - }
    60  - 
    61  - let mut previous_inode = inode;
    62  - let mut parent_dentry = unsafe { (*(*file).f_path.dentry).d_parent };
    63  - for _ in 0..MAX_DIR_DEPTH {
    64  - if parent_dentry.is_null() {
    65  - break;
    66  - }
    67  - let inode = unsafe { (*(*parent_dentry).d_inode).i_ino };
    68  - if inode == previous_inode {
    69  - break;
    70  - }
    71  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    72  - ALERT_FILE_OPEN.output(
    73  - &ctx,
    74  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    75  - 0,
    76  - );
    77  - return Ok(-1);
    78  - }
    79  - previous_inode = inode;
    80  - parent_dentry = unsafe { (*parent_dentry).d_parent };
    81  - }
    82  - }
     50 + if let Some(paths) = unsafe { DENIED_FILE_OPEN.get(&INODE_WILDCARD) } {
     51 + if paths.paths[0] == 0 {
     52 + return check_conditions_and_alert(
     53 + &ctx,
     54 + &ALLOWED_FILE_OPEN,
     55 + file,
     56 + inode,
     57 + binprm_inode,
     58 + Mode::Allowlist,
     59 + );
     60 + }
     61 + }
    83 62   
    84  - if let Some(paths) = unsafe { DENIED_FILE_OPEN.get(&binprm_inode) } {
    85  - if paths.paths[0] == 0 {
    86  - ALERT_FILE_OPEN.output(
    87  - &ctx,
    88  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    89  - 0,
    90  - );
    91  - return Ok(-1);
    92  - }
     63 + Action::Allow
     64 +}
    93 65   
    94  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    95  - ALERT_FILE_OPEN.output(
    96  - &ctx,
    97  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    98  - 0,
    99  - );
    100  - return Ok(-1);
    101  - }
     66 +#[inline(always)]
     67 +fn check_conditions_and_alert(
     68 + ctx: &LsmContext,
     69 + map: &HashMap<u64, Paths>,
     70 + file: *const file,
     71 + inode: u64,
     72 + binprm_inode: u64,
     73 + mode: Mode,
     74 +) -> Action {
     75 + match check_conditions(map, file, inode, binprm_inode, mode) {
     76 + Action::Allow => Action::Allow,
     77 + Action::Deny => {
     78 + ALERT_FILE_OPEN.output(ctx, &AlertFileOpen::new(ctx.pid(), binprm_inode, inode), 0);
     79 + Action::Deny
     80 + }
     81 + }
     82 +}
    102 83   
    103  - let mut previous_inode = inode;
    104  - let mut parent_dentry = unsafe { (*(*file).f_path.dentry).d_parent };
    105  - for _ in 0..MAX_DIR_DEPTH {
    106  - if parent_dentry.is_null() {
    107  - break;
    108  - }
    109  - let inode = unsafe { (*(*parent_dentry).d_inode).i_ino };
    110  - if inode == previous_inode {
    111  - break;
    112  - }
    113  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    114  - ALERT_FILE_OPEN.output(
    115  - &ctx,
    116  - &AlertFileOpen::new(ctx.pid(), binprm_inode, inode),
    117  - 0,
    118  - );
    119  - return Ok(-1);
    120  - }
    121  - previous_inode = inode;
    122  - parent_dentry = unsafe { (*parent_dentry).d_parent };
    123  - }
    124  - }
     84 +#[inline(always)]
     85 +fn check_conditions(
     86 + map: &HashMap<u64, Paths>,
     87 + file: *const file,
     88 + inode: u64,
     89 + binprm_inode: u64,
     90 + mode: Mode,
     91 +) -> Action {
     92 + if let Some(paths) = unsafe { map.get(&INODE_WILDCARD) } {
     93 + if let Some(action) = check_paths(&paths.paths, file, inode, &mode) {
     94 + return action;
    125 95   }
    126 96   }
    127 97   
    128  - if let Some(paths) = unsafe { DENIED_FILE_OPEN.get(&INODE_WILDCARD) } {
    129  - if paths.paths[0] == 0 {
    130  - if let Some(paths) = unsafe { ALLOWED_FILE_OPEN.get(&INODE_WILDCARD) } {
    131  - if paths.paths[0] == 0 {
    132  - return Ok(0);
    133  - }
     98 + if let Some(paths) = unsafe { map.get(&binprm_inode) } {
     99 + if let Some(action) = check_paths(&paths.paths, file, inode, &mode) {
     100 + return action;
     101 + }
     102 + }
    134 103   
    135  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    136  - return Ok(0);
    137  - }
     104 + match mode {
     105 + Mode::Allowlist => Action::Deny,
     106 + Mode::Denylist => Action::Allow,
     107 + }
     108 +}
    138 109   
    139  - let mut previous_inode = inode;
    140  - let mut parent_dentry = unsafe { (*(*file).f_path.dentry).d_parent };
    141  - for _ in 0..MAX_DIR_DEPTH {
    142  - if parent_dentry.is_null() {
    143  - break;
    144  - }
    145  - let inode = unsafe { (*(*parent_dentry).d_inode).i_ino };
    146  - if inode == previous_inode {
    147  - break;
    148  - }
    149  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    150  - return Ok(0);
    151  - }
    152  - previous_inode = inode;
    153  - parent_dentry = unsafe { (*parent_dentry).d_parent };
    154  - }
    155  - }
     110 +#[inline(always)]
     111 +fn check_paths(
     112 + paths: &[u64; MAX_PATHS],
     113 + file: *const file,
     114 + inode: u64,
     115 + mode: &Mode,
     116 +) -> Option<Action> {
     117 + if paths[0] == 0 {
     118 + return Some(match mode {
     119 + Mode::Allowlist => Action::Allow,
     120 + Mode::Denylist => Action::Deny,
     121 + });
     122 + }
    156 123   
    157  - if let Some(paths) = unsafe { ALLOWED_FILE_OPEN.get(&binprm_inode) } {
    158  - if paths.paths[0] == 0 {
    159  - return Ok(0);
    160  - }
     124 + if paths[..MAX_PATHS - 1].contains(&inode) {
     125 + return Some(match mode {
     126 + Mode::Allowlist => Action::Allow,
     127 + Mode::Denylist => Action::Deny,
     128 + });
     129 + }
    161 130   
    162  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    163  - return Ok(0);
    164  - }
     131 + check_parents(paths, file, inode, mode)
     132 +}
    165 133   
    166  - let mut previous_inode = inode;
    167  - let mut parent_dentry = unsafe { (*(*file).f_path.dentry).d_parent };
    168  - for _ in 0..MAX_DIR_DEPTH {
    169  - if parent_dentry.is_null() {
    170  - break;
    171  - }
    172  - let inode = unsafe { (*(*parent_dentry).d_inode).i_ino };
    173  - if inode == previous_inode {
    174  - break;
    175  - }
    176  - if paths.paths[..MAX_PATHS - 1].contains(&inode) {
    177  - return Ok(0);
    178  - }
    179  - previous_inode = inode;
    180  - parent_dentry = unsafe { (*parent_dentry).d_parent };
    181  - }
    182  - }
    183  - ALERT_FILE_OPEN.output(&ctx, &AlertFileOpen::new(ctx.pid(), binprm_inode, inode), 0);
    184  - return Ok(-1);
     134 +#[inline(always)]
     135 +fn check_parents(
     136 + paths: &[u64; MAX_PATHS],
     137 + file: *const file,
     138 + mut previous_inode: u64,
     139 + mode: &Mode,
     140 +) -> Option<Action> {
     141 + let mut parent_dentry = unsafe { (*(*file).f_path.dentry).d_parent };
     142 + for _ in 0..MAX_DIR_DEPTH {
     143 + if parent_dentry.is_null() {
     144 + break;
     145 + }
     146 + let inode = unsafe { (*(*parent_dentry).d_inode).i_ino };
     147 + if inode == previous_inode {
     148 + break;
     149 + }
     150 + if paths[..MAX_PATHS - 1].contains(&inode) {
     151 + return Some(match mode {
     152 + Mode::Allowlist => Action::Allow,
     153 + Mode::Denylist => Action::Deny,
     154 + });
    185 155   }
     156 + previous_inode = inode;
     157 + parent_dentry = unsafe { (*parent_dentry).d_parent };
    186 158   }
    187 159   
    188  - Ok(0)
     160 + None
    189 161  }
    190 162   
  • ■ ■ ■ ■ ■ ■
    guardity-ebpf/src/lib.rs
    skipped 13 lines
    14 14  #[allow(dead_code)]
    15 15  pub mod vmlinux;
    16 16   
     17 +pub enum Mode {
     18 + Allowlist,
     19 + Denylist,
     20 +}
     21 + 
     22 +pub enum Action {
     23 + Allow,
     24 + Deny,
     25 +}
     26 + 
     27 +impl From<Action> for i32 {
     28 + fn from(action: Action) -> Self {
     29 + match action {
     30 + Action::Allow => 0,
     31 + Action::Deny => -1,
     32 + }
     33 + }
     34 +}
     35 + 
  • ■ ■ ■ ■
    guardity-ebpf/src/main.rs
    skipped 17 lines
    18 18   
    19 19  #[lsm(name = "file_open")]
    20 20  pub fn prog_file_open(ctx: LsmContext) -> i32 {
    21  - match file_open(ctx) {
    22  - Ok(ret) => ret,
    23  - Err(_) => 0,
    24  - }
     21 + file_open(ctx).into()
    25 22  }
    26 23   
    27 24  #[lsm(name = "task_fix_setuid")]
    skipped 28 lines
Please wait...
Page is in error, reload to recover