mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 00:14:44 +01:00
Revert "utils/emacs: add apparmor-mode.el"
This reverts commit 65b0f83aea
.
Signed-off-by: Alex Murray <alex.murray@canonical.com>
This commit is contained in:
parent
4c8a27457e
commit
2b1ddef16e
2 changed files with 1 additions and 426 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
apparmor-
|
||||
apparmor-*
|
||||
cscope.*
|
||||
binutils/aa-enabled
|
||||
binutils/aa-enabled.1
|
||||
|
@ -180,7 +180,6 @@ utils/apparmor/*.pyc
|
|||
utils/apparmor/rule/*.pyc
|
||||
utils/apparmor.egg-info/
|
||||
utils/build/
|
||||
!utils/emacs/apparmor-mode.el
|
||||
utils/htmlcov/
|
||||
utils/test/common_test.pyc
|
||||
utils/test/.coverage
|
||||
|
|
|
@ -1,424 +0,0 @@
|
|||
;;; apparmor-mode.el --- Major mode for editing AppArmor policy files -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (c) 2018 Alex Murray
|
||||
|
||||
;; Author: Alex Murray <murray.alex@gmail.com>
|
||||
;; Maintainer: Alex Murray <murray.alex@gmail.com>
|
||||
;; URL: https://gitlab.com/apparmor/apparmor
|
||||
;; Version: 0.8.2
|
||||
;; Package-Requires: ((emacs "26.1"))
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; This program is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; 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, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; The following documentation sources were used:
|
||||
;; https://gitlab.com/apparmor/apparmor/wikis/QuickProfileLanguage
|
||||
;; https://gitlab.com/apparmor/apparmor/wikis/ProfileLanguage
|
||||
|
||||
;; TODO:
|
||||
;; - do smarter completion syntactically via regexps
|
||||
;; - decide if to use entire line regexp for statements or
|
||||
;; - not (ie just a subset?) if we use regexps above then
|
||||
;; - should probably keep full regexps here so can reuse
|
||||
;; - expand highlighting of mount rules (options=...) similar to dbus
|
||||
;; - add tests via ert etc
|
||||
|
||||
;;;; Setup
|
||||
|
||||
;; (require 'apparmor-mode)
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; for flycheck integration
|
||||
(declare-function flycheck-define-command-checker "ext:flycheck.el"
|
||||
(symbol docstring &rest properties))
|
||||
(declare-function flycheck-valid-checker-p "ext:flycheck.el")
|
||||
(defvar flycheck-checkers)
|
||||
|
||||
(defgroup apparmor nil
|
||||
"Major mode for editing AppArmor policies."
|
||||
:group 'tools)
|
||||
|
||||
(defcustom apparmor-mode-indent-offset 2
|
||||
"Indentation offset in `apparmor-mode' buffers."
|
||||
:type 'integer
|
||||
:group 'apparmor)
|
||||
|
||||
(defvar apparmor-mode-keywords '("all" "audit" "capability" "chmod" "delegate"
|
||||
"dbus" "deny" "file" "flags" "io_uring" "include"
|
||||
"include if exists" "link" "mount" "mqueue"
|
||||
"network" "on" "owner" "pivot_root" "profile"
|
||||
"quiet" "remount" "rlimit" "safe" "subset" "to"
|
||||
"umount" "unsafe" "userns"))
|
||||
|
||||
(defvar apparmor-mode-profile-flags '("enforce" "complain" "debug" "kill"
|
||||
"chroot_relative" "namespace_relative"
|
||||
"attach_disconnected" "no_attach_disconnected"
|
||||
"chroot_attach" "chroot_no_attach"
|
||||
"unconfined"))
|
||||
|
||||
(defvar apparmor-mode-capabilities '("audit_control" "audit_write" "chown"
|
||||
"dac_override" "dac_read_search" "fowner"
|
||||
"fsetid" "ipc_lock" "ipc_owner" "kill"
|
||||
"lease" "linux_immutable" "mac_admin"
|
||||
"mac_override" "mknod" "net_admin"
|
||||
"net_bind_service" "net_broadcast"
|
||||
"net_raw" "setfcap" "setgid" "setpcap"
|
||||
"setuid" "syslog" "sys_admin" "sys_boot"
|
||||
"sys_chroot" "sys_module" "sys_nice"
|
||||
"sys_pacct" "sys_ptrace" "sys_rawio"
|
||||
"sys_resource" "sys_time"
|
||||
"sys_tty_config"))
|
||||
|
||||
(defvar apparmor-mode-network-permissions '("create" "accept" "bind" "connect"
|
||||
"listen" "read" "write" "send"
|
||||
"receive" "getsockname" "getpeername"
|
||||
"getsockopt" "setsockopt" "fcntl"
|
||||
"ioctl" "shutdown" "getpeersec"
|
||||
"sqpoll" "override_creds"))
|
||||
|
||||
(defvar apparmor-mode-network-domains '("inet" "ax25" "ipx" "appletalk" "netrom"
|
||||
"bridge" "atmpvc" "x25" "inet6" "rose"
|
||||
"netbeui" "security" "key" "packet"
|
||||
"ash" "econet" "atmsvc" "sna" "irda"
|
||||
"pppox" "wanpipe" "bluetooth" "unix"))
|
||||
|
||||
(defvar apparmor-mode-network-types '("stream" "dgram" "seqpacket" "raw" "rdm"
|
||||
"packet" "dccp"))
|
||||
|
||||
;; TODO: this is not complete since is not fully documented
|
||||
(defvar apparmor-mode-network-protocols '("tcp" "udp" "icmp"))
|
||||
|
||||
(defvar apparmor-mode-dbus-permissions '("r" "w" "rw" "send" "receive"
|
||||
"acquire" "bind" "read" "write"))
|
||||
|
||||
(defvar apparmor-mode-rlimit-types '("fsize" "data" "stack" "core" "rss" "as"
|
||||
"memlock" "msgqueue" "nofile" "locks"
|
||||
"sigpending" "nproc" "rtprio" "cpu"
|
||||
"nice"))
|
||||
|
||||
(defvar apparmor-mode-abi-regexp "^\\s-*\\(#?abi\\)\\s-+\\([<\"][[:graph:]]+[\">]\\)")
|
||||
|
||||
(defvar apparmor-mode-include-regexp "^\\s-*\\(#?include\\( if exists\\)?\\)\\s-+\\([<\"][[:graph:]]+[\">]\\)")
|
||||
|
||||
(defvar apparmor-mode-capability-regexp (concat "^\\s-*\\(capability\\)\\s-+\\("
|
||||
(regexp-opt apparmor-mode-capabilities)
|
||||
"\\s-*\\)*"))
|
||||
|
||||
(defvar apparmor-mode-variable-name-regexp "@{[[:alpha:]_]+}")
|
||||
|
||||
(defvar apparmor-mode-variable-regexp
|
||||
(concat "^\\s-*\\(" apparmor-mode-variable-name-regexp "\\)\\s-*\\(\\+?=\\)\\s-*\\([[:graph:]]+\\)\\(\\s-+\\([[:graph:]]+\\)\\)?\\s-*\\(#.*\\)?$"))
|
||||
|
||||
(defvar apparmor-mode-profile-name-regexp "[[:alnum:]]+")
|
||||
|
||||
(defvar apparmor-mode-profile-attachment-regexp "[][[:alnum:]*@/_{},-.?]+")
|
||||
|
||||
(defvar apparmor-mode-profile-flags-regexp
|
||||
(concat "\\(flags\\)=(\\(" (regexp-opt apparmor-mode-profile-flags) "\\s-*\\)*)") )
|
||||
|
||||
(defvar apparmor-mode-profile-regexp
|
||||
(concat "^\\s-*\\(\\(profile\\)\\s-+\\(\\(" apparmor-mode-profile-name-regexp "\\)\\s-+\\)?\\)?\\(\\^?" apparmor-mode-profile-attachment-regexp "\\)\\(\\s-+" apparmor-mode-profile-flags-regexp "\\)?\\s-+{\\s-*$"))
|
||||
|
||||
(defvar apparmor-mode-file-rule-permissions-regexp "[CPUaciklmpruwx]+")
|
||||
|
||||
(defvar apparmor-mode-file-rule-permissions-prefix-regexp
|
||||
(concat "^\\s-*\\(\\(audit\\|owner\\|deny\\)\\s-+\\)*\\(file\\s-+\\)?"
|
||||
"\\(" apparmor-mode-file-rule-permissions-regexp "\\)\\s-+"
|
||||
"\\(" apparmor-mode-profile-attachment-regexp "\\)\\s-*"
|
||||
"\\(->\\s-+\\(" apparmor-mode-profile-attachment-regexp "\\)\\)?\\s-*"
|
||||
","))
|
||||
|
||||
(defvar apparmor-mode-file-rule-permissions-suffix-regexp
|
||||
(concat "^\\s-*\\(\\(audit\\|owner\\|deny\\)\\s-+\\)*\\(file\\s-+\\)?"
|
||||
"\\(" apparmor-mode-profile-attachment-regexp "\\)\\s-+"
|
||||
"\\(" apparmor-mode-file-rule-permissions-regexp "\\)\\s-*"
|
||||
"\\(->\\s-+\\(" apparmor-mode-profile-attachment-regexp "\\)\\)?\\s-*"
|
||||
","))
|
||||
|
||||
(defvar apparmor-mode-network-rule-regexp
|
||||
(concat
|
||||
"^\\s-*\\(\\(audit\\|quiet\\|deny\\)\\s-+\\)*network\\s-*"
|
||||
"\\(" (regexp-opt apparmor-mode-network-permissions 'words) "\\)?\\s-*"
|
||||
"\\(" (regexp-opt apparmor-mode-network-domains 'words) "\\)?\\s-*"
|
||||
"\\(" (regexp-opt apparmor-mode-network-types 'words) "\\)?\\s-*"
|
||||
"\\(" (regexp-opt apparmor-mode-network-protocols 'words) "\\)?\\s-*"
|
||||
;; TODO: address expression
|
||||
"\\(delegate to\\s-+\\(" apparmor-mode-profile-attachment-regexp "\\)\\)?\\s-*"
|
||||
","))
|
||||
|
||||
(defvar apparmor-mode-dbus-rule-regexp
|
||||
(concat
|
||||
"^\\s-*\\(\\(audit\\|deny\\)\\s-+\\)?dbus\\s-*"
|
||||
"\\(\\(bus\\)=\\(system\\|session\\)\\)?\\s-*"
|
||||
"\\(\\(dest\\)=\\([[:alpha:].]+\\)\\)?\\s-*"
|
||||
"\\(\\(path\\)=\\([[:alpha:]/]+\\)\\)?\\s-*"
|
||||
"\\(\\(interface\\)=\\([[:alpha:].]+\\)\\)?\\s-*"
|
||||
"\\(\\(method\\)=\\([[:alpha:]_]+\\)\\)?\\s-*"
|
||||
;; permissions - either a single permission or multiple permissions in
|
||||
;; parentheses with commas and whitespace separating
|
||||
"\\("
|
||||
(regexp-opt apparmor-mode-dbus-permissions 'words)
|
||||
"\\|"
|
||||
"("
|
||||
(regexp-opt apparmor-mode-dbus-permissions 'words)
|
||||
"\\("
|
||||
(regexp-opt apparmor-mode-dbus-permissions 'words) ",\\s-+"
|
||||
"\\)"
|
||||
"\\)?\\s-*"
|
||||
","))
|
||||
|
||||
(defvar apparmor-mode-font-lock-defaults
|
||||
`(((,(regexp-opt apparmor-mode-keywords 'symbols) . font-lock-keyword-face)
|
||||
(,(regexp-opt apparmor-mode-rlimit-types 'symbols) . font-lock-type-face)
|
||||
;; comma at end-of-line
|
||||
(",\\s-*$" . 'font-lock-builtin-face)
|
||||
;; TODO be more specific about where these are valid
|
||||
("->" . 'font-lock-builtin-face)
|
||||
("[=\\+()]" . 'font-lock-builtin-face)
|
||||
("+=" . 'font-lock-builtin-face)
|
||||
("<=" . 'font-lock-builtin-face) ; rlimit
|
||||
;; abi
|
||||
(,apparmor-mode-abi-regexp
|
||||
(1 font-lock-preprocessor-face t)
|
||||
(2 font-lock-string-face t))
|
||||
;; includes
|
||||
(,apparmor-mode-include-regexp
|
||||
(1 font-lock-preprocessor-face t)
|
||||
(3 font-lock-string-face t))
|
||||
;; variables
|
||||
(,apparmor-mode-variable-name-regexp 0 font-lock-variable-name-face t)
|
||||
;; profiles
|
||||
(,apparmor-mode-profile-regexp
|
||||
(4 font-lock-function-name-face t nil)
|
||||
(5 font-lock-variable-name-face t))
|
||||
;; capabilities
|
||||
(,apparmor-mode-capability-regexp 2 font-lock-type-face t)
|
||||
;; file rules
|
||||
(,apparmor-mode-file-rule-permissions-prefix-regexp
|
||||
(3 font-lock-keyword-face nil t) ; class
|
||||
(4 font-lock-constant-face t) ; permissions
|
||||
(7 font-lock-function-name-face nil t)) ;profile
|
||||
(,apparmor-mode-file-rule-permissions-suffix-regexp
|
||||
(3 font-lock-keyword-face nil t) ; class
|
||||
(5 font-lock-constant-face t) ; permissions
|
||||
(7 font-lock-function-name-face nil t)) ;profile
|
||||
;; network rules
|
||||
(,apparmor-mode-network-rule-regexp
|
||||
(3 font-lock-constant-face t) ;permissions
|
||||
(4 font-lock-function-name-face t) ;domain
|
||||
(5 font-lock-variable-name-face t) ;type
|
||||
(6 font-lock-type-face t)) ; protocol
|
||||
;; dbus rules
|
||||
(,apparmor-mode-dbus-rule-regexp
|
||||
(4 font-lock-variable-name-face t) ;bus
|
||||
(5 font-lock-constant-face t) ;system/session
|
||||
(7 font-lock-variable-name-face t) ;dest
|
||||
(10 font-lock-variable-name-face t)
|
||||
(13 font-lock-variable-name-face t)
|
||||
(16 font-lock-variable-name-face t)))))
|
||||
|
||||
(defvar apparmor-mode-syntax-table
|
||||
(let ((table (make-syntax-table)))
|
||||
;; # is comment start
|
||||
(modify-syntax-entry ?# "<" table)
|
||||
;; newline finishes comment line
|
||||
(modify-syntax-entry ?\n ">" table)
|
||||
;; / and + is used in path names which we want to treat as an entire word
|
||||
(modify-syntax-entry ?/ "w" table)
|
||||
(modify-syntax-entry ?+ "w" table)
|
||||
table))
|
||||
|
||||
(defun apparmor-mode-complete-include (prefix &optional local)
|
||||
"Return list of completions of include for PREFIX which could be LOCAL."
|
||||
(let* ((file-name (file-name-base prefix))
|
||||
(parent (file-name-directory prefix))
|
||||
(directory (concat (if local default-directory "/etc/apparmor.d") "/"
|
||||
parent)))
|
||||
;; need to prepend all of directory part of prefix
|
||||
(mapcar (lambda (f) (concat parent f))
|
||||
(file-name-all-completions file-name directory))))
|
||||
|
||||
;; TODO - make a lot smarter than just keywords - complete paths from the
|
||||
;; system if we look like a path, do sub-completion based on the current lines
|
||||
;; keyword etc - ie match against syntax highlighting regexes and use those to
|
||||
;; further complete etc
|
||||
(defun apparmor-mode-completion-at-point ()
|
||||
"`completion-at-point' function for `apparmor-mode'."
|
||||
(let ((prefix (or (thing-at-point 'word t) ""))
|
||||
(bounds (bounds-of-thing-at-point 'word))
|
||||
(bol (save-excursion (beginning-of-line) (point)))
|
||||
(candidates nil))
|
||||
(setq candidates
|
||||
(cond ((looking-back "#?include\\s-+\\([<\"]\\)[[:graph:]]*" bol)
|
||||
(apparmor-mode-complete-include
|
||||
prefix (string= (match-string 1) "\"")))
|
||||
(t apparmor-mode-keywords)))
|
||||
(list (car bounds) ; start
|
||||
(cdr bounds) ; end
|
||||
candidates
|
||||
:company-docsig #'identity)))
|
||||
|
||||
(defun apparmor-mode-indent-line ()
|
||||
"Indent current line in `apparmor-mode'."
|
||||
(interactive)
|
||||
(if (bolp)
|
||||
(apparmor-mode--indent-line)
|
||||
(save-excursion
|
||||
(apparmor-mode--indent-line))))
|
||||
|
||||
(defun apparmor-mode--indent-line ()
|
||||
"Indent current line in `apparmor-mode'."
|
||||
(beginning-of-line)
|
||||
(cond
|
||||
((bobp)
|
||||
;; simple case indent to 0
|
||||
(indent-line-to 0))
|
||||
((looking-at "^\\s-*}\\s-*$")
|
||||
;; block closing, deindent relative to previous line
|
||||
(indent-line-to (save-excursion
|
||||
(forward-line -1)
|
||||
(max 0 (- (current-indentation) apparmor-mode-indent-offset)))))
|
||||
;; other cases need to look at previous lines
|
||||
(t
|
||||
(indent-line-to (save-excursion
|
||||
(forward-line -1)
|
||||
;; keep going backwards until we have a line with actual
|
||||
;; content since blank lines don't count
|
||||
(while (and (looking-at "^\\s-*$")
|
||||
(not (bobp)))
|
||||
(forward-line -1))
|
||||
(cond
|
||||
((looking-at "\\(^.*{[^}]*$\\)")
|
||||
;; previous line opened a block, indent to that line
|
||||
(+ (current-indentation) apparmor-mode-indent-offset))
|
||||
(t
|
||||
;; default case, indent the same as previous line
|
||||
(current-indentation))))))))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode apparmor-mode prog-mode "AppArmor"
|
||||
"Major mode for editing AppArmor profiles."
|
||||
:syntax-table apparmor-mode-syntax-table
|
||||
(setq font-lock-defaults apparmor-mode-font-lock-defaults)
|
||||
(setq-local indent-line-function #'apparmor-mode-indent-line)
|
||||
(add-to-list 'completion-at-point-functions #'apparmor-mode-completion-at-point)
|
||||
(setq imenu-generic-expression `(("Profiles" ,apparmor-mode-profile-regexp 5)))
|
||||
(setq comment-start "#")
|
||||
(setq comment-end "")
|
||||
(when (require 'flycheck nil t)
|
||||
(unless (flycheck-valid-checker-p 'apparmor)
|
||||
(flycheck-define-command-checker 'apparmor
|
||||
"A checker using apparmor_parser. "
|
||||
:command '("apparmor_parser"
|
||||
"-Q" ;; skip kernel load
|
||||
"-K" ;; skip cache
|
||||
source)
|
||||
:error-patterns '((error line-start "AppArmor parser error at line "
|
||||
line ": " (message)
|
||||
line-end)
|
||||
(error line-start "AppArmor parser error for "
|
||||
(one-or-more not-newline)
|
||||
" in profile " (file-name)
|
||||
" at line " line ": " (message)
|
||||
line-end))
|
||||
:modes '(apparmor-mode)))
|
||||
(add-to-list 'flycheck-checkers 'apparmor t)))
|
||||
|
||||
;; flymake integration
|
||||
(defvar-local apparmor-mode--flymake-proc nil)
|
||||
|
||||
(defun apparmor-mode-flymake (report-fn &rest _args)
|
||||
"`flymake' backend function for `apparmor-mode' to report errors via REPORT-FN."
|
||||
;; disable if apparmor_parser is not available
|
||||
(unless (executable-find "apparmor_parser")
|
||||
(error "Cannot find apparmor_parser"))
|
||||
|
||||
;; kill any existing running instance
|
||||
(when (process-live-p apparmor-mode--flymake-proc)
|
||||
(kill-process apparmor-mode--flymake-proc))
|
||||
|
||||
(let ((source (current-buffer))
|
||||
(contents (buffer-substring (point-min) (point-max))))
|
||||
;; when the current buffer is an abstraction then fake a profile around it so
|
||||
;; we can check it
|
||||
(when (and (buffer-file-name)
|
||||
(string-match-p ".*/abstractions/.*" (buffer-file-name)))
|
||||
(setq contents (format "profile %s { %s }" (buffer-name) contents)))
|
||||
(save-restriction
|
||||
(widen)
|
||||
;; Reset the `apparmor-mode--flymake-proc' process to a new process
|
||||
;; calling check-syntax.
|
||||
(setq
|
||||
apparmor-mode--flymake-proc
|
||||
(make-process
|
||||
:name "apparmor-mode-flymake" :noquery t :connection-type 'pipe
|
||||
;; Make output go to a temporary buffer.
|
||||
:buffer (generate-new-buffer " *apparmor-mode-flymake*")
|
||||
;; TODO: specify the base directory so that includes resolve correctly
|
||||
;; rather than using the system ones
|
||||
:command '("apparmor_parser" "-Q" "-K" "/dev/stdin")
|
||||
:sentinel
|
||||
(lambda (proc _event)
|
||||
(when (memq (process-status proc) '(exit signal))
|
||||
(unwind-protect
|
||||
;; Only proceed if `proc' is the same as
|
||||
;; `apparmor-mode--flymake-proc', which indicates that
|
||||
;; `proc' is not an obsolete process.
|
||||
;;
|
||||
(if (with-current-buffer source (eq proc apparmor-mode--flymake-proc))
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(goto-char (point-min))
|
||||
;; Parse the output buffer for diagnostic's
|
||||
;; messages and locations, collect them in a list
|
||||
;; of objects, and call `report-fn'.
|
||||
;;
|
||||
(cl-loop
|
||||
while (search-forward-regexp
|
||||
"^\\(AppArmor parser error \\(?:for /dev/stdin in profile .*\\)?at line \\)\\([0-9]+\\): \\(.*\\)$"
|
||||
nil t)
|
||||
for msg = (match-string 3)
|
||||
for (beg . end) = (flymake-diag-region
|
||||
source
|
||||
(string-to-number (match-string 2)))
|
||||
for type = :error
|
||||
collect (flymake-make-diagnostic source beg end type msg)
|
||||
into diags
|
||||
finally (funcall report-fn diags)))
|
||||
(flymake-log :warning "Cancelling obsolete check %s" proc))
|
||||
;; Cleanup the temporary buffer used to hold the
|
||||
;; check's output.
|
||||
(kill-buffer (process-buffer proc)))))))
|
||||
(process-send-string apparmor-mode--flymake-proc contents)
|
||||
(process-send-eof apparmor-mode--flymake-proc))))
|
||||
|
||||
;;;###autoload
|
||||
(defun apparmor-mode-setup-flymake-backend ()
|
||||
"Setup the `flymake' backend for `apparmor-mode'."
|
||||
(add-hook 'flymake-diagnostic-functions 'apparmor-mode-flymake nil t))
|
||||
|
||||
;;;###autoload
|
||||
(add-hook 'apparmor-mode-hook 'apparmor-mode-setup-flymake-backend)
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\`/etc/apparmor\\.d/" . apparmor-mode))
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\`/var/lib/snapd/apparmor/profiles/" . apparmor-mode))
|
||||
|
||||
|
||||
(provide 'apparmor-mode)
|
||||
;;; apparmor-mode.el ends here
|
Loading…
Add table
Reference in a new issue