[apparmor] [patch] [27/38] Implement FileRule logprof_header()

Christian Boltz apparmor at cboltz.de
Fri Aug 12 21:02:44 UTC 2016


Hello,

$subject.

Merge the existing and requested permissions into a nice set of headers
that can be displayed by aa-logprof. This will look like:

	Path:      /foo
	Old Mode:  r + owner w
	New Mode:  rw

Also split off a _join_given_perms() function off _joint_perms() so that
we can use the permission string merging for things not stored in 
self.*.

Finally add some tests for logprof_header().



[ 27-logprof_header.diff ]

=== modified file ./utils/apparmor/rule/file.py
--- utils/apparmor/rule/file.py	2016-05-26 20:37:44.752619167 +0200
+++ utils/apparmor/rule/file.py	2016-05-26 22:58:48.436023890 +0200
@@ -218,16 +218,20 @@
             raise AppArmorBug('Invalid combination of path and perms in 
file rule - either specify path and perms, or none of them')
 
     def _joint_perms(self):
-        '''return the permissions as string'''
+        '''return the permissions as string (using self.perms and 
self.exec_perms)'''
+        return self._join_given_perms(self.perms, self.exec_perms)
+
+    def _join_given_perms(self, perms, exec_perms):
+        '''return the permissions as string (using the perms and 
exec_perms given as parameter)'''
         perm_string = ''
         for perm in file_permissions:
-            if perm in self.perms:
+            if perm in perms:
                 perm_string = perm_string + perm
 
-        if self.exec_perms == self.ANY_EXEC:
+        if exec_perms == self.ANY_EXEC:
             raise AppArmorBug("FileRule.ANY_EXEC can't be used for 
actual rules")
-        if self.exec_perms:
-            perm_string = perm_string + self.exec_perms
+        if exec_perms:
+            perm_string = perm_string + exec_perms
 
         return perm_string
 
@@ -323,24 +327,42 @@
         return severity
 
     def logprof_header_localvars(self):
+        headers = []
+
+        path = logprof_value_or_all(self.path, self.all_paths)
+        headers += [_('Path'), path]
+
+        old_mode = ''
+        if self.original_perms:
+            original_perms_all = 
self._join_given_perms(self.original_perms['allow']['all'], None)
+            original_perms_owner = 
self._join_given_perms(self.original_perms['allow']['owner'] - 
self.original_perms['allow']['all'], None)  # only list owner perms that 
are not covered by other perms
+
+            if original_perms_all and original_perms_owner:
+                old_mode = '%s + owner %s' % (original_perms_all, 
original_perms_owner)
+            elif original_perms_all:
+                old_mode = original_perms_all
+            elif original_perms_owner:
+                old_mode = 'owner %s' % original_perms_owner
+            else:
+                old_mode = ''
+
+        if old_mode:
+            headers += [_('Old Mode'), old_mode]
+
+        perms = logprof_value_or_all(self.perms, self.all_perms)
+        if self.perms or self.exec_perms:
+            perms = self._joint_perms()
+
         if self.owner:
-            owner = _('Yes')
-        else:
-            owner = _('No')
+            perms = 'owner %s' % perms
+
+        if not self.all_targets:
+            perms = "%s -> %s" % (perms, self.target.regex)
+
+        headers += [_('New Mode'), perms]
 
-        path    = logprof_value_or_all(self.path,       self.all_paths)
-        perms   = logprof_value_or_all(self.perms,      self.all_perms)
-        if self.exec_perms:
-            perms = perms + self.exec_perms
-        target  = logprof_value_or_all(self.target,     
self.all_targets)
-
-        return [
-            _('Owner only'),    owner,
-            _('Path'),          path,
-            _('Permissions'),   perms,
-            _('Target'),        target,
-            # file_keyword and leading_perms are not really relevant
-        ]
+        # file_keyword and leading_perms are not really relevant
+        return headers
 
     def glob(self):
         '''Change path to next possible glob'''
=== modified file ./utils/test/test-file.py
--- utils/test/test-file.py	2016-05-26 20:37:44.752619167 +0200
+++ utils/test/test-file.py	2016-05-26 23:38:13.568258370 +0200
@@ -722,25 +722,34 @@
         rank = obj.severity(sev_db)
         self.assertEqual(rank, expected)
 
+class FileLogprofHeaderTest(AATest):
+    tests = [
+        # log event                        old perms ALL / owner
+        (['file,',                              set(),      set()       
], [                               _('Path'), _('ALL'),                                         
_('New Mode'), _('ALL')                 ]),
+        (['/foo r,',                            set(),      set()       
], [                               _('Path'), '/foo',                                           
_('New Mode'), 'r'                      ]),
+        (['file /bar Px -> foo,',               set(),      set()       
], [                               _('Path'), '/bar',                                           
_('New Mode'), 'Px -> foo'              ]),
+        (['deny file,',                         set(),      set()       
], [_('Qualifier'), 'deny',        _('Path'), _('ALL'),                                         
_('New Mode'), _('ALL')                 ]),
+        (['allow file /baz rwk,',               set(),      set()       
], [_('Qualifier'), 'allow',       _('Path'), '/baz',                                           
_('New Mode'), 'rwk'                    ]),
+        (['audit file /foo mr,',                set(),      set()       
], [_('Qualifier'), 'audit',       _('Path'), '/foo',                                           
_('New Mode'), 'mr'                     ]),
+        (['audit deny /foo wk,',                set(),      set()       
], [_('Qualifier'), 'audit deny',  _('Path'), '/foo',                                           
_('New Mode'), 'wk'                     ]),
+        (['owner file /foo ix,',                set(),      set()       
], [                               _('Path'), '/foo',                                           
_('New Mode'), 'owner ix'               ]),
+        (['audit deny file /foo rlx -> /baz,',  set(),      set()       
], [_('Qualifier'), 'audit deny',  _('Path'), '/foo',                                           
_('New Mode'), 'rlx -> /baz'            ]),
+        (['/foo rw,',                           set('r'),   set()       
], [                               _('Path'), '/foo',         _('Old 
Mode'), _('r'),            _('New Mode'), _('rw')                  ]),
+        (['/foo rw,',                           set(),      set('rw')   
], [                               _('Path'), '/foo',         _('Old 
Mode'), _('owner rw'),     _('New Mode'), _('rw')                  ]),
+        (['/foo mrw,',                          set('r'),   set('k')    
], [                               _('Path'), '/foo',         _('Old 
Mode'), _('r + owner k'),  _('New Mode'), _('mrw')                 ]),
+        (['/foo mrw,',                          set('r'),   set('rk')   
], [                               _('Path'), '/foo',         _('Old 
Mode'), _('r + owner k'),  _('New Mode'), _('mrw')                 ]),
+   ]
 
-#class FileLogprofHeaderTest(AATest):
-#    tests = [
-#        ('file,',                        [                               
_('Access mode'), _('ALL'),    _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('file (send receive),',         [                               
_('Access mode'), 'receive send', _('Bus'), _('ALL'), _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('file send bus=session,',       [                               
_('Access mode'), 'send',      _('Bus'), 'session',   _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('deny file,',                   [_('Qualifier'), 'deny',        
_('Access mode'), _('ALL'),    _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('allow file send,',             [_('Qualifier'), 'allow',       
_('Access mode'), 'send',      _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('audit file send bus=session,', [_('Qualifier'), 'audit',       
_('Access mode'), 'send',      _('Bus'), 'session',   _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('audit deny file send,',        [_('Qualifier'), 'audit deny',  
_('Access mode'), 'send',      _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('file bind exec_perms=bind.exec_perms,',    [                               
_('Access mode'), 'bind',      _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), 'bind.exec_perms', _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), _('ALL')]),
-#        ('file send bus=session path=/path target=aa.test owner=ExMbr 
peer=(exec_perms=(peer.exec_perms)),',
-#                                         [                               
_('Access mode'), 'send',      _('Bus'), 'session',   _('Path'), '/
path',  _('Name'), _('ALL'),    _('Interface'), 'aa.test', _('Member'), 
'ExMbr',  _('Peer exec_perms'), 'peer.exec_perms',_('Peer label'), 
_('ALL')]),
-#        ('file send peer=(label=foo),',  [                               
_('Access mode'), 'send',      _('Bus'), _('ALL'),    _('Path'), 
_('ALL'), _('Name'), _('ALL'),    _('Interface'), _('ALL'),  
_('Member'), _('ALL'), _('Peer exec_perms'), _('ALL'),   _('Peer 
label'), 'foo'   ]),
-#   ]
-#
-#    def _run_test(self, params, expected):
-#        obj = FileRule._parse(params)
-#        self.assertEqual(obj.logprof_header(), expected)
+    def _run_test(self, params, expected):
+        obj = FileRule._parse(params[0])
+        if params[1] or params[2]:
+            obj.original_perms = {'allow': { 'all': params[1], 'owner': 
params[2]}}
+        self.assertEqual(obj.logprof_header(), expected)
+
+    def test_empty_original_perms(self):
+        obj = FileRule._parse('/foo rw,')
+        obj.original_perms = {'allow': { 'all': set(), 'owner': set()}}
+        self.assertEqual(obj.logprof_header(), [_('Path'), '/foo', 
_('New Mode'), _('rw')])
 
 class FileEditHeaderTest(AATest):
     def _run_test(self, params, expected):



Regards,

Christian Boltz
-- 
Alte Programmiererweisheit:
Was man nicht in Assembler programmieren kann, muß man löten.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20160812/f7bd3b3c/attachment.pgp>


More information about the AppArmor mailing list