Cerb Configuration Language Reference

Table of Contents

1 Introduction

CCL is a language for configuring CerbNG access control rules. It has been designed to provide flexible and convenient mechanism for describing CerbNG behavior in analysing and performing system call access control.

CCL is very different from "language" used for configuring the original Cerb. The syntax resembles syntax of C programming language. C programmers will be familiar with most constructs of CCL. You should know C to understand this guide after first reading, because it is rather terse.

2 Usage

You write a program in CCL using text editor of your choice. When the program is finished, you can `execute' it using cbctl utility, which compiles the code and loads it into kernel. Sample cbctl invocation:

# cbctl -f myrules.cb

-f switch makes cbctl read rules from file following it (by default rules are read from standard input). -p switch turns off cpp(1) preprocessing of the rules file before loading it. Other switches are: -l for listing the rules for verification, -t displays CCL parsing tree for the file before loading it, -n prevents loading the rules into kernel (it doesn't block listing the rules with -l and -t switches though). For full option listing run cbctl -h.

3 Structure

CCL is a high level language. It operates on objects which are really low level kernel structures, but lets you see them from a "bird's eye view".

A program in CCL consists of a series of statements executed from top to bottom. The only exception to this rule are conditionals which are described below. Statements are separated with semicolons. Some statements have side-effects (like assignments and system calls), others just return value, which can be used for comparisons, as one of arguments in function call or as operand for one of built-in operators.

The single most important element of CCL syntax are conditionals. CerbNG's main purpose if filtering access to system calls, so comparing syscall numbers to predefined list, validating syscall arguments and process variables is main part of CerbNG programming.

CCL conditionals look like those in C, namely:

if (some condition) {
  	statement_a;
  	statement_b;
	...
} else {
  	statement_m;
  	statement_n;
  	statement_o;	
	...
}

(the else { ... } part is optional, braces enclosing statement blocks are mandatory)

Conditional itself is a statement, thus conditionals can and often are nested. Conditionals do not return value. Depending on value returned by condition check, the first or the second part of conditional statement series is executed. The only false value in CCL is 0. Any other value is equivalent to boolean truth. There is no special type for logical truth and false in CCL.

Examples of conditions:

Expression Boolean Value
1 < 2 true
0 false
2 - 5 true
function() equal to value returned by function call
"some string" true

CCL is a full blown programming language. It has its limitations, but lets you do many things which other programming languages can. Syntax of expressions as you can see above is similar to expressions in C language. Other expressions are also similar:

Expression Explanation
function(x, y, z) Function call with arguments
return 0 Returning value to userland
retval = call() Execution of current syscall and assignment of returned value to some variable
reg[0] = reg[1]& 0xf0f0 Assignment of internal register array

4 Built-in types

There are three basic types of objects in CCL: integers, strings and variables.

4.1 Integers

Integers can be signed or unsinged. Integers can be obtained directly ie. as written value (1, -4, and so on) or indirectly as a result of function call or operation. There are many arithmetical and logical operators which take integers as arguments. Most of them are identical to C operators (for full list of operators, their precedence and binding see Appendix A). Each operator having integers as arguments returns integer. Some examples of expressions using integers:

Expression Result Comment
1- 2 * 3 -5 Result of operations on positive numbers can be negative
1 + (11 % 3) 3 Precedence of operations can be explicitly set using parentheses
7 / 2 3 Division operator returns floor of real result. No floating point numbers support
1 > 5 0 Comparisons return number
! 9 0 Logical operators return numbers

4.2 Strings

Strings are texts enclosed in double apostroph signs. The only three available string operations are equality comparison, concatenation and matching. Checking string equality is done using == operator. Concatenation of strings is done by the compiler, so no variables can be used as arguments. Matching strings to patterns takes form of expression @ pattern. For convenience there is an operator checking of given string and pattern don't match - !@. String expressions examples:

Expression Result Comment
"aaa" == "b" 0 false
"aa" == "aa" 1 true
"foobar" @ "fo*b?r" 1 true
"foo" "bar" "foobar" concatenation

4.3 Arrays

Arrays are variables containing one or more values. Consecutive values are referenced by indexing variable name. Like array[<element number>]. Arrays may contain elements of different types.

4.4 Variables and registers

Variables in Cerb are not declared. Their type is type of value assigned to them.

Cerb for storing things uses so called registers. Registers are available by array named reg. You can assign and retrieve each register by accessing consecutive array slots, like this:

reg[0] = call();
return reg[0];

Using registers is not convenient, since you have to memorize the indices every time you utilize them. CCL compiler alleviates the problem mapping variable names of your choice to registers. Thus expressions like:

myvar = 10;

are equivalent to accessing register associated with particular variable. Registers for variable mappings are allocated from 16 up. Registers 0-15 are so called scratch registers. You can use them for storing temporary values. Maximum number of registers is defined as CB_NREGS_G in file kcerb/cerb_globals.h.

There is a special class of registers - global registers. You reference them as elements of array greg. They are different from standard registers by their persistence. Values stored in global registers are kept between consecutive Cerb entry points. One simple example of their usage is counting how many times some syscall have been run to limit number of syscall invocations (eg. keep a network daemon from binding to socket more than once). Number of global registers is defined as CB_NGREGS_G in file kcerb/cerb_globals.h

4.5 Arguments

Most syscalls have some arguments, which modify their actions. Arguments of each syscall are available through array named arg. This array is indexed from 0 to number of arguments of currently analyzed syscall. You can check and modify arguments of syscalls reading and assigning elements of this array.

4.6 Process parameters

Assigning and reading of some variables has predefined meaning. These variables, modify current process environment. For full list see Appendix B.

Appendix A - Operator table

(growing precedence)

Operators Operands Binding
= binary right
|| binary left
&& binary left
| binary left
^ binary left
& binary left
== != binary left
@ !@ (pattern matching) binary left
< <= > >= binary left
<< >> binary left (available only during compilation)
+ - binary left (available only during compilation)
* / % binary left (available only during compilation)
! ~ - unary right

All of the above operators work identically to C language operators

Appendix B - Process parameters

Variable name Description
syscall (UDEF) Number of currently intercepted syscall. If return value is equal SYS_MAXSYSCALL, it means that CerbNG rules have just been loaded and one can take any initialization steps needed
syscallname (STR) Name of currently intercepted syscall
errno (DEF) Error number of last operation (it is not return value of executed syscall)
pname (STR) Current process name
pid (UDEF) Process ID
ppid (UDEF) Parent process ID
pgid (UDEF) ID of primary group process owner belongs to
ruid (UDEF) Real user ID of process owner
rgid (UDEF) Real user group ID of process owner
euid (UDEF) Effective user ID of process owner
egid (UDEF) Effective group ID of process owner
svuid (UDEF) Saved user ID of process owner
svgid (UDEF) Saved group ID of process owner
groups (UDEFPTR) GID Numbers of all groups process owner is member of
umask (UDEF) Umask value of current process
login (STR) Login name of session owner
prison (ST_PRISON) Pointer to prison structure of current process (if it is executed in jail). Available functions for this structure: isjailed(), getjailip(), getjailhost()
cdir (STR) Current directory of process
rdir (STR) Root directory of current process
jdir (STR) Jail directory of current process
retval0 (DEF) Return value of syscall
retval1 (DEF) Additional return value of syscall (used if COMPAT_43 or COMPAT_SUNOS are defined)
fname (STR) File name of executed image
finode (UDEF) Inode number of current process executable file
fdev (UDEF) Device number of current process executable file
fuid (UDEF) User ID of current process executable file
fgid (UDEF) Group ID of current process executable file
fmode (UDEF) Mode bits of current process executable file (chmod(1))
ftype (UDEF) Type of current process executable file (stat(2)) (XXX)
fflags (UDEF) Flags of current process executable file (chflags(1))
fnlinks (UDEF) Number of hard links of current process executable file
fsize (UDEF) Size of current process executable file