aboutsummaryrefslogtreecommitdiffhomepage
path: root/notes/unsafe_slul.txt
blob: 77f1c79ccf53f454aa4935f553496d9f2bbca827 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

Unsafe "SLUL"
=============

SLUL will not have any way to escape safety rules/checks. But in order to
allow the runtime library to be written in "SLUL", it is necssary to allow
unsafe code somehow.

Solution: The "CrashFast" language
----------------------------------
Changes compared to SLUL:

- File extension is .crhf (or maybe .yolo)
- Main file is sysmain.crhf (sysmain.yolo)
- Header starts with \crashfast (\yolo) instead of \slul
- Unsafe features!

Name of "CrashFast"
-------------------
- CrashFast?
- YoloLang? (with .yolo extension? and \yolo header?)
- UhohLang? (.uhoh and \uhoh)
- UnsafeLang?

Preventing usage of "CrashFast"
-------------------------------
Require some additional compiler options?

    cslul --__crash__fast_ --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd
    cslul --language=_crash_fast --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd
    /usr/local/lib/cslul/crashfast --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd
    /usr/local/libexec/cslul/crashfast --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd

Perhaps use a wrapper, "/usr/bin/crashfast", that modifies the args?

    cslul --crash-fast=$(printf '\b') --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd
    cslul --crash-fast=$(printf '\n') --build-syslib --i-know-what-i-am-doing=ddf5f7e88fb39330d0bd

Best solution?

    - require the option "--__crash__fast_" ("--__caution__yololang_")
    - require either of "--freestanding" or "--hosted"
    - require a README.txt or README.md file that BEGINS with the following contents
      (with \n, \r\n, or \r endings)

 Warning
 =======
 This code is written in the CrashFast programming language, which is a
 modified variant of SLUL that allows unsafe operations. CrashFast is
 only intended to be used for implementing the SLUL runtime library.
 
 WARNING: CrashFast code can have security exploits that allow code
 execution and/or allow bypassing security restrictions that would
 have been applied to normal SLUL code.
 
 Removal of this notice will prevent compilation!


Unsafe features
---------------
* Type casts
* Making array length assumptions
* Making ownership assumptions
* Making boolean/null assumptions
* Unchecked arithmetic
* (Raw assembly?)
* Raw hexcode
    * With macro support?
* "Static if" for architecture detection


Hexcode
-------

Alt. 1: Similar to macros in C:

    hexconst R1 0x41
    hexfunc ADDI(ra,rb,rc) emit(0x42, rc, ra, rb)
    func f(int x) {
        int y
        UNSAFE hexcode in(R0=x) out(y=R2) clobber(none) {
            ADDI(R2,R1,R1)
        }
    }

Alt. 2: Very basic variant:

    hexcode ADDI__R2_R1_R1   0x42   0x42 0x41 0x41

    func f(int x) {
        int y
        UNSAFE hexcode {
            hexsave r1 r2
            hexld r1 x
            ADDI__R2_R1_R1
            hexst r2 y
            hexrestore x
        }
    }

Alt. 3: Very basic variant with funny names:

    hexconst ADDI__R2_R1_R1   0x42   0x42 0x41 0x41

    func f(int x) {
        int y
        UNSAFE hexconst {
            hexfly r1 r2
            hexld r1 x
            ADDI__R2_R1_R1
            hexst r2 y
            hexland x
        }
    }

Special entry points
--------------------

_ifsys windows {
    func UNSAFE bare pe_entrypoint() noreturn {
        ...
    }
} _elsesys linux {
    func UNSAFE bare _start() noreturn {
        ...
    }
}

Here, UNSAFE means that:
1. the following identifier is a special identifier,
   which creates some kind of special function.
2. the function can have special keywords
   ("bare" in this case)



Static if
---------
With special cases for all architectures:

    UNSAFE hexcode {
        _ifsys rv64 {
            hexsave r1 r2
            hexld r1 x
            ADDI__R2_R1_R1
            hexst r2 y
            hexrestore x
        } _elsesys aarch64 {
            ...
        } _elsesys i386 {
            ...
        }
    }

With special cases for only some architectures:

    _ifsys rv64 {
        UNSAFE hexcode {
            hexsave r1 r2
            hexld r1 x
            ADDI__R2_R1_R1
            hexst r2 y
            hexrestore x
        }
    } _elsesys aarch64 {
        ...
    } _elsesys { }

_ifsys/_elsesys could be handled in the tokenizer.

For _ifsys/_elsesys it should be required to have { } in order to
simplify the tokenizer!

_ifsys/_elsesys have underscores in order to allow for future usage of
ifsys/elsesys keywords in SLUL (which could have different semantics).


UNSAFE syntax
-------------

    # Obviously unsafe features
    UNSAFE hexcode x86_64 { ... }
    UNSAFE assume p != none
    UNSAFE cast p ref Thing
    UNSAFE assume_own p
    UNSAFE assume_unown p
    [UNSAFE]int array
    func UNSAFE bare f() noreturn { ... }

Should there be an "unassert" statement?

    unassert p != none
    unassert len < 5
    # After this line, we can no longer assume that p!=none and that len<5

Also: Forcing a (re-)read or write of variables:

    _writemem obj1
    UNSAFE(read) silently_use_obj1()

    UNSAFE(write) silently_modify_obj2()
    _readmem obj2

    _volatile obj3 {
        UNSAFE(readwrite) silently_use_modify_obj3()
    }


Alternative solution: Capabilities + Minimal assembly files
-----------------------------------------------------------

Idea: Perhaps there could be capabilities that the "root arena" of the main
module does not have?

Perhaps an object called SlulSystem, which is never passed to SlulApp.main?
(and which there is not way to obtain a reference to)

slulrt public header:

    type SlulSystem

slulrt_asm public header:

    type SysCallArg
    # p = pointer, z = size_t, i = int, o = off_t
    func SlulSystem.syscall_pziiio()
    func SlulSystem.syscall6(
        ref SysCallArg arg1,
        ref SysCallArg arg2,
        ref SysCallArg arg3,
        ref SysCallArg arg4,
        ref SysCallArg arg5,
        ref SysCallArg arg6,
        )

inside slulrt:

    type AnyData

    # private function!
    func SlulSystem.mmap(ref AnyData addr, usize length, int prot, int flags, int fd, fileoffs off) -> ref AnyData
    {
        ref SysCallArg ret = this.syscall6(
            .arg1=.from_anydata(addr),
            .arg2=.from_usize(length),
            .arg3=.from_int(prot),
            .arg4=.from_int(flags),
            .arg5=.from_int(fd),
            .arg6=.from_fileoffs(off))
        return .from_sysret(ret)
    }

Building slulrt:

* assembly code -> slulrt_asm.o
* slul code     -> slulrt_slul.o
* then these can be linked into libslulrt.so
* should there be OS-specific parts? probably? (and both slul and asm parts)