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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
|
<?xml version="1.0" encoding="iso-8859-1"?>
<sect1 id="safe-haskell">
<title>Safe Haskell</title>
<indexterm><primary>safe haskell</primary></indexterm>
<para>
Safe Haskell is an extension to the Haskell language that is implemented in
GHC as of version 7.2. It allows for unsafe code to be securely included in a
trusted code base by restricting the features of GHC Haskell the code is
allowed to use. Put simply, it makes the types of programs trustable.
</para>
<para>
While a primary use case of Safe Haskell is running untrusted code, Safe
Haskell doesn't provide this directly. Instead, Safe Haskell provides strict
type safety. Without Safe Haskell, GHC allows many exceptions to the type
system which can subvert any abstractions. By providing strict type safety,
Safe Haskell enables developers to build their own library level sandbox
mechanisms to run untrusted code.
</para>
<para>
While Safe Haskell is an extension, it actually runs in the background for
every compilation with GHC. It does this to track the type violations of
modules to infer their safety, even when they aren't explicitly using Safe
Haskell. Please refer to section <xref linkend="safe-inference"/> for more
details of this.
</para>
<para>
The design of Safe Haskell covers the following aspects:
<itemizedlist>
<listitem>A <link linkend="safe-language">safe language</link> dialect of
Haskell that provides stricter guarantees about the code. It allows types
and module boundaries to be trusted.
</listitem>
<listitem>A <emphasis>safe import</emphasis> extension that specifies that
the module being imported must be trusted.
</listitem>
<listitem>A definition of <emphasis>trust</emphasis> (or safety) and how it
operates, along with ways of defining and changing the trust of modules
and packages.
</listitem>
</itemizedlist>
</para>
<para>
Safe Haskell, however, <emphasis>does not offer</emphasis> compilation
safety. During compilation time it is possible for arbitrary processes to be
launched, using for example the <link linkend="pre-processor">custom
pre-processor</link> flag. This can be manipulated to either compromise a
users system at compilation time, or to modify the source code just before
compilation to try to alter Safe Haskell flags. This is discussed further in
section <xref linkend="safe-compilation"/>.
</para>
<sect2 id="safe-use-cases">
<title>Uses of Safe Haskell</title>
<indexterm><primary>safe haskell uses</primary></indexterm>
<para>
Safe Haskell has been designed with two use cases in mind:
<itemizedlist>
<listitem>Enforcing strict type safety at compile time</listitem>
<listitem>Compiling and executing untrusted code</listitem>
</itemizedlist>
</para>
<sect3>
<title>Strict type-safety (good style)</title>
Haskell offers a powerful type system and separation of pure and
effectual functions through the <literal>IO</literal> monad. However,
there are several loop holes in the type system, the most obvious being
the <literal>unsafePerformIO :: IO a -> a</literal> function. The safe
language dialect of Safe Haskell disallows the use of such functions.
This can be useful restriction as it makes Haskell code easier to analyse
and reason about. It also codifies the existing culture in the Haskell
community of trying to avoid unsafe functions unless absolutely
necessary. As such, using the safe language (through the
<option>-XSafe</option> flag) can be thought of as a way of enforcing
good style, similar to the function of <option>-Wall</option>.
</sect3>
<sect3>
<title>Building secure systems (restricted IO Monads)</title>
<indexterm><primary>secure haskell</primary></indexterm>
<para>
Systems such as information flow control security, capability based
security systems and DSLs for working with encrypted data.. etc can be
built in the Haskell language as a library. However they require
guarantees about the properties of Haskell that aren't true in general
due to the presence of functions like <literal>unsafePerformIO
</literal>. Safe Haskell gives users enough guarantees about the type
system to allow them to build such secure systems.
</para>
<para>
As an example, lets define an interface for a plugin system where the
plugin authors are untrusted, possibly malicious third-parties. We do
this by restricting the plugin interface to pure functions or to a
restricted <literal>IO</literal> monad that we have defined. The
restricted <literal>IO</literal> monad will only allow a safe subset of
<literal>IO</literal> actions to be executed. We define the plugin
interface so that it requires the plugin module,
<literal>Danger</literal>, to export a single computation,
<literal>Danger.runMe</literal>, of type <literal>RIO ()</literal>, where
<literal>RIO</literal> is a monad defined as follows:
</para>
<programlisting>
-- While we use `Safe', the `Trustworthy' pragma would also be
-- fine. We simply want to ensure that:
-- 1) The module exports an interface that untrusted code can't
-- abuse.
-- 2) Untrusted code can import this module.
--
{-# LANGUAGE Safe #-}
module RIO (RIO(), runRIO, rioReadFile, rioWriteFile) where
-- Notice that symbol UnsafeRIO is not exported from this module!
newtype RIO a = UnsafeRIO { runRIO :: IO a }
instance Monad RIO where
return = UnsafeRIO . return
(UnsafeRIO m) >>= k = UnsafeRIO $ m >>= runRIO . k
-- Returns True iff access is allowed to file name
pathOK :: FilePath -> IO Bool
pathOK file = {- Implement some policy based on file name -}
rioReadFile :: FilePath -> RIO String
rioReadFile file = UnsafeRIO $ do
ok <- pathOK file
if ok then readFile file else return ""
rioWriteFile :: FilePath -> String -> RIO ()
rioWriteFile file contents = UnsafeRIO $ do
ok <- pathOK file
if ok then writeFile file contents else return ()
</programlisting>
We then compile the <literal>Danger</literal> plugin using the new Safe
Haskell <option>-XSafe</option> flag:
<programlisting>
{-# LANGUAGE Safe #-}
module Danger ( runMe ) where
runMe :: RIO ()
runMe = ...
</programlisting>
<para>
Before going into the Safe Haskell details, lets point out some of the
reasons this security mechanism would fail without Safe Haskell:
</para>
<itemizedlist>
<listitem>The design attempts to restrict the operations that
<literal>Danger</literal> can perform by using types, specifically
the <literal>RIO</literal> type wrapper around <literal>IO</literal>.
The author of <literal>Danger</literal> can subvert this though by
simply writing arbitrary <literal>IO</literal> actions and using
<literal>unsafePerformIO :: IO a -> a</literal> to execute them as
pure functions.
</listitem>
<listitem>The design also relies on <literal>Danger</literal> not being
able to access the <literal>UnsafeRIO</literal> constructor.
Unfortunately Template Haskell can be used to subvert module
boundaries and so could be used to gain access to this constructor.
</listitem>
<listitem>There is no way to place restrictions on the modules that
<literal>Danger</literal> can import. This gives the author of
<literal>Danger</literal> a very large attack surface, essentially
any package currently installed on the system. Should any of these
packages have a vulnerability, then the <literal>Danger</literal>
module can exploit it.
</listitem>
</itemizedlist>
<para>
Safe Haskell prevents all these attacks. This is done by compiling the
RIO module with the <option>-XSafe</option> or
<option>-XTrustworthy</option> flag and compiling
<literal>Danger</literal> with the <option>-XSafe</option> flag. We
explain each below.
</para>
<para>
The use of <option>-XSafe</option> to compile
<literal>Danger</literal> restricts the features of Haskell that can be used
to a <link linkend="safe-language">safe subset</link>. This
includes disallowing <literal>unsafePerformIO</literal>,
Template Haskell, pure FFI functions, RULES and restricting the
operation of Overlapping Instances. The <option>-XSafe</option>
flag also restricts the modules can be imported by
<literal>Danger</literal> to only those that are considered trusted.
Trusted modules are those compiled with <option>-XSafe</option>, where
GHC provides a mechanical guarantee that the code is safe. Or those
modules compiled with <option>-XTrustworthy</option>, where the module
author claims that the module is Safe.
</para>
<para>
This is why the RIO module is compiled with <option>-XSafe</option> or
<option>-XTrustworthy</option>>, to allow the <literal>Danger</literal>
module to import it. The <option>-XTrustworthy</option> flag doesn't
place any restrictions on the module like <option>-XSafe</option> does
(expect to restrict overlapping instances to
<link linkend="safe-overlapping-instances">safe overlapping
instances</link>). Instead the module author claims that while code
may use unsafe features internally, it only exposes an API that can used
in a safe manner.
</para>
<para>
However, the unrestricted use of <option>-XTrustworthy</option> is a
problem as an arbitrary module can use it to mark themselves as
trusted, yet <option>-XTrustworthy</option> doesn't offer any
guarantees about the module, unlike <option>-XSafe</option>.
To control the use of trustworthy modules it is recommended to use the
<option>-fpackage-trust</option> flag. This flag adds an extra
requirement to the trust check for trustworthy modules.
It requires that for a trustworthy modules to be considered trusted, and
allowed to be used in <option>-XSafe</option> compiled code, the client C
compiling the code must tell GHC that they trust the package the
trustworthy module resides in.
This is essentially a way of for C to say, while this package contains
trustworthy modules that can be used by untrusted modules compiled with
<option>-XSafe</option>, I trust the author(s) of this package and trust
the modules only expose a safe API. The trust of a package can be
changed at any time, so if a vulnerability found in a package, C can
declare that package untrusted so that any future compilation against
that package would fail. For a more detailed overview of this mechanism
see <xref linkend="safe-trust"/>.
</para>
<para>
In the example, <literal>Danger</literal> can import module
<literal>RIO</literal> because <literal>RIO</literal> is compiled with
<option>-XSafe</option>. Thus, <literal>Danger</literal> can make use of
the <literal>rioReadFile</literal> and <literal>rioWriteFile</literal>
functions to access permitted file names. The main application then
imports both <literal>RIO</literal> and <literal>Danger</literal>. To run
the plugin, it calls <literal>RIO.runRIO Danger.runMe</literal> within
the <literal>IO</literal> monad. The application is safe in the knowledge
that the only <literal>IO</literal> to ensue will be to files whose paths
were approved by the <literal>pathOK</literal> test.
</para>
</sect3>
</sect2>
<sect2 id="safe-language">
<title>Safe Language</title>
<indexterm><primary>safe language</primary></indexterm>
The Safe Haskell <emphasis>safe language</emphasis> (enabled by
<option>-XSafe</option>) guarantees the following properties:
<itemizedlist>
<listitem><emphasis>Referential transparency</emphasis> — The types
can be trusted. Any pure function, is guaranteed to be pure. Evaluating
them is deterministic and won't cause any side effects. Functions in
the <literal>IO</literal> monad are still allowed and behave as usual.
So, for example, the <literal>unsafePerformIO :: IO a -> a</literal>
function is disallowed in the safe language to enforce this property.
</listitem>
<listitem><emphasis>Module boundary control</emphasis> — Only
symbols that are publicly available through other module export lists
can be accessed in the safe language. Values using data constructors
not exported by the defining module, cannot be examined or created. As
such, if a module M establishes some invariants through careful use of
its export list, then code written in the safe language that imports M
is guaranteed to respect those invariants.
</listitem>
<listitem><emphasis>Semantic consistency</emphasis> — For any
module that imports a module written in the safe language, expressions
that compile both with and without the safe import have the same
meaning in both cases. That is, importing a module written in the safe
language cannot change the meaning of existing code that isn't
dependent on that module. So, for example, there are some restrictions
placed on the use of <emphasis><link linkend="instance-overlap">
Overlapping Instances</link></emphasis>, as these can violate this
property.
</listitem>
<listitem><emphasis>Strict subset</emphasis> — The safe language is
strictly a subset of Haskell as implemented by GHC. Any expression that
compiles in the safe language has the same meaning as it does when
compiled in normal Haskell.
</listitem>
</itemizedlist>
<para>
These four properties guarantee that in the safe language you can trust the
types, can trust that module export lists are respected, and can trust that
code that successfully compiles has the same meaning as it normally would.
</para>
<para>
To achieve these properties, in the safe language dialect we disable
completely the following features:
<itemizedlist>
<listitem><emphasis>TemplateHaskell</emphasis> — Can be used to
gain access to constructors and abstract data types that weren't
exported by a module, subverting module boundaries.
</listitem>
</itemizedlist>
</para>
<para>
Furthermore, we restrict the following features:
<itemizedlist>
<listitem><emphasis>ForeignFunctionInterface</emphasis> — Foreign
import declarations that import a function with a non-IO type are
disallowed.
</listitem>
<listitem><emphasis>RULES</emphasis> — RULES defined in a module M
compiled with <option>-XSafe</option> are dropped. RULES defined in
trustworthy modules that M imports are still valid and will fire as
usual.
</listitem>
<listitem><emphasis>OverlappingInstances</emphasis> — There is no
restriction on the creation of overlapping instances, but we do
restrict their use at a particular call site. This is a detailed
restriction, please refer to
<link linkend="safe-overlapping-instances">Safe Overlapping Instances
</link> for details.
</listitem>
<listitem><emphasis>GeneralisedNewtypeDeriving</emphasis> — GND is
not allowed in the safe language. This is due to the ability of it to
violate module boundaries when module authors forget to put nominal
role annotations on their types as appropriate. For this reason, the
<literal>Data.Coerce</literal> module is also considered unsafe. We are
hoping to find a better solution here in the future.
</listitem>
<listitem><emphasis>Data.Typeable</emphasis> — Hand crafted
instances of the Typeable type class are not allowed in Safe Haskell as
this can easily be abused to unsafely coerce between types. Derived
instances (through the <link linkend="deriving-typeable"><option>
-XDeriveDataTypeable</option></link> extension) are still allowed.
</listitem>
</itemizedlist>
</para>
<sect3 id="safe-overlapping-instances">
<title>Safe Overlapping Instances</title>
<para>
Due to the semantic consistency guarantee of Safe Haskell, we must
restrict the function of overlapping instances. We don't restrict their
ability to be defined, as this is a global property and not something we
can determine by looking at a single module. Instead, when a module calls
a function belonging to a type-class, we check that the instance
resolution done is considered 'safe'. This check is enforced for modules
compiled with both <option>-XSafe</option> and
<option>-XTrustworthy</option>.
</para>
<para>
More specifically, consider the following modules:
<programlisting>
{-# LANGUAGE Safe #-}
module Class (TC(..)) where
class TC a where { op :: a -> String }
{-# LANGUAGE Safe #-}
module Dangerous (TC(..)) where
import Class
instance
{-# OVERLAPS #-}
TC [Int] where { op _ = "[Int]" }
{-# LANGUAGE Safe #-}
module TCB_Runner where
import Class
import Dangerous
instance
TC [a] where { op _ = "[a]" }
f :: String
f = op ([1,2,3,4] :: [Int])
</programlisting>
Both module Class and module Dangerous will compile under
<option>-XSafe</option> without issue. However, in module TCB_Runner, we
must check if the call to <literal>op</literal> in function
<literal>f</literal> is safe.
</para>
<para>
What does it mean to be Safe? That importing a module compiled with
<option>-XSafe</option> shouldn't change the meaning of code that
compiles fine without importing the module. This is the Safe Haskell
property known as <emphasis>semantic consistency</emphasis>.
</para>
<para>
In our situation, module TCB_Runner compiles fine without importing
module Dangerous. So when deciding which instance to use for the call to
<literal>op</literal>, if we determine the instance <literal>TC
[Int]</literal> from module Dangerous is the most specific, this is
unsafe. This prevents code written by third-parties we don't trust (which
is compiled using <option>-XSafe</option> in Safe Haskell) from changing
the behaviour of our existing code.
</para>
<para>
Specifically, we apply the following rule to determine if a type-class
method call is <emphasis>unsafe</emphasis> when overlapping instances are
involved:
<itemizedlist>
<listitem>Most specific instance, <literal>Ix</literal>, defined in an
`-XSafe` compiled module.
</listitem>
<listitem><literal>Ix</literal> is an orphan instance or a
multi-parameter-type-class.
</listitem>
<listitem>At least one overlapped instance, <literal>Iy</literal>, is both:
<itemizedlist>
<listitem>From a different module than <literal>Ix</literal></listitem>
<listitem><literal>Iy</literal> is not marked
<option>OVERLAPPABLE</option></listitem>
</itemizedlist>
</listitem>
</itemizedlist>
This is a slightly involved heuristic, but captures the situation of an
imported module N changing the behaviour of existing code. For example, if
the second condition isn't violated, then the module author M must depend
either on a type-class or type defined in N.
</para>
<para>
When an particular type-class method call is considered unsafe due to
overlapping instances, and the module being compiled is using
<option>-XSafe</option> or <option>-XTrustworthy</option>, then
compilation will fail. For <option>-XUnsafe</option>, no restriction is
applied, and for modules using safe inference, they will be inferred
unsafe.
</para>
</sect3>
</sect2>
<sect2 id="safe-imports">
<title>Safe Imports</title>
<indexterm><primary>safe imports</primary></indexterm>
Safe Haskell enables a small extension to the usual import syntax of
Haskell, adding a <emphasis>safe</emphasis> keyword:
<programlisting>
impdecl -> import [safe] [qualified] modid [as modid] [impspec]
</programlisting>
When used, the module being imported with the safe keyword must be a
trusted module, otherwise a compilation error will occur. The safe import
extension is enabled by either of the <option>-XSafe</option>,
<option>-XTrustworthy</option>, or <option>-XUnsafe</option> flags. When
the <option>-XSafe</option> flag is used, the safe keyword is allowed but
meaningless, as every import is treated as a safe import.
</sect2>
<sect2 id="safe-trust">
<title>Trust and Safe Haskell Modes</title>
<indexterm><primary>safe haskell trust</primary></indexterm>
<indexterm><primary>trust</primary></indexterm>
Safe Haskell introduces the following three language flags:
<itemizedlist>
<listitem><emphasis>-XSafe</emphasis> — Enables the safe language
dialect, asking GHC to guarantee trust. The safe language dialect
requires that all imports be trusted or a compilation error will occur.
Safe Haskell will also infer this safety type for modules automatically
when possible. Please refer to section <xref linkend="safe-inference"/>
for more details of this.
</listitem>
<listitem><emphasis>-XTrustworthy</emphasis> — Means that while
this module may invoke unsafe functions internally, the module's author
claims that it exports an API that can't be used in an unsafe way. This
doesn't enable the safe language. It does however restrict the
resolution of overlapping instances to only allow
<link linkend="safe-overlapping-instances">safe overlapping
instances</link>. The trust guarantee is provided by the module
author, not GHC. An import statement with the safe keyword results in a
compilation error if the imported module is not trusted. An import
statement without the keyword behaves as usual and can import any
module whether trusted or not.
</listitem>
<listitem><emphasis>-XUnsafe</emphasis> — Marks the module being
compiled as unsafe so that modules compiled using
<option>-XSafe</option> can't import it. You may want to explicitly
mark a module unsafe when it exports internal constructors that can be
used to violate invariants.
</listitem>
</itemizedlist>
<para>
While these are flags, they also correspond to Safe Haskell module types
that a module can have. You can think of using these as declaring an
explicit contract (or type) that a module must have. If it is invalid, then
compilation will fail. GHC will also infer the correct type for Safe
Haskell, please refer to section <xref linkend="safe-inference"/> for more
details.
</para>
<para>
The procedure to check if a module is trusted or not depends on if the
<option>-fpackage-trust</option> flag is present. The check is similar in
both cases with the <option>-fpackage-trust</option> flag enabling an extra
requirement for trustworthy modules to be regarded as trusted.
</para>
<sect3>
<title>Trust check (<option>-fpackage-trust</option> disabled)</title>
<indexterm><primary>trust check</primary></indexterm>
<para>
A <emphasis>module M in a package P is trusted by a client C</emphasis>
if and only if:
<itemizedlist>
<listitem>Both of these hold:
<itemizedlist>
<listitem>The module was compiled with <option>-XSafe</option>
</listitem>
<listitem>All of M's direct imports are trusted by C</listitem>
</itemizedlist>
</listitem>
<listitem><emphasis>OR</emphasis> all of these hold:
<itemizedlist>
<listitem>The module was compiled with
<option>-XTrustworthy</option></listitem>
<listitem>All of M's direct <emph>safe imports</emph>are trusted by
C</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</para>
<para>
The above definition of trust has an issue. Any module can be compiled
with <option>-XTrustworthy</option> and it will be trusted. To control
this, there is an additional definition of package trust (enabled with the
<option>-fpackage-trust</option> flag). The point of package trust is to
require that the client C explicitly say which packages are allowed to
contain trustworthy modules. Trustworthy packages are only trusted if
they reside in a package trusted by C.
</para>
</sect3>
<sect3>
<title>Trust check (<option>-fpackage-trust</option> enabled)</title>
<indexterm><primary>trust check</primary></indexterm>
<indexterm><primary>-fpackage-trust</primary></indexterm>
<para>
When the <option>-fpackage-trust</option> flag is enabled, whether or not
a module is trusted depends on if certain packages are trusted. Package
trust is determined by the client C invoking GHC (i.e. you).
</para>
<para>
Specifically, a package <emphasis>P is trusted</emphasis> when one of
these hold:
<itemizedlist>
<listitem>C's package database records that P is trusted (and no
command-line arguments override this)</listitem>
<listitem>C's command-line flags say to trust P regardless of what is
recorded in the package database.</listitem>
</itemizedlist>
</para>
<para>
In either case, C is the only authority on package trust. It is up to the
client to decide which <link linkend="safe-package-trust">packages they
trust</link>.
</para>
<para>
When the <option>-fpackage-trust</option> flag is used a <emphasis>module M from
package P is trusted by a client C</emphasis> if and only if:
<itemizedlist>
<listitem>Both of these hold:
<itemizedlist>
<listitem> The module was compiled with <option>-XSafe</option>
</listitem>
<listitem> All of M's direct imports are trusted by C</listitem>
</itemizedlist>
</listitem>
<listitem><emphasis>OR</emphasis> all of these hold:
<itemizedlist>
<listitem>The module was compiled with
<option>-XTrustworthy</option></listitem>
<listitem>All of M's direct safe imports are trusted by C</listitem>
<listitem>Package P is trusted by C</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</para>
<para>
For the first trust definition the trust guarantee is provided by GHC
through the restrictions imposed by the safe language. For the second
definition of trust, the guarantee is provided initially by the
module author. The client C then establishes that they trust the
module author by indicating they trust the package the module resides
in. This trust chain is required as GHC provides no guarantee for
<literal>-XTrustworthy</literal> compiled modules.
</para>
<para>
The reason there are two modes of checking trust is that the extra
requirement enabled by <option>-fpackage-trust</option> causes the design
of Safe Haskell to be invasive. Packages using Safe Haskell when the flag
is enabled may or may not compile depending on the state of trusted
packages on a users machine. This is both fragile, and causes compilation
failures for everyone, even if they aren't trying to use any of the
guarantees provided by Safe Haskell. Disabling
<option>-fpackage-trust</option> by default and turning it into a flag
makes Safe Haskell an opt-in extension rather than an always on feature.
</para>
</sect3>
<sect3 id="safe-trust-example">
<title>Example</title>
<programlisting>
Package Wuggle:
{-# LANGUAGE Safe #-}
module Buggle where
import Prelude
f x = ...blah...
Package P:
{-# LANGUAGE Trustworthy #-}
module M where
import System.IO.Unsafe
import safe Buggle
</programlisting>
<para>
Suppose a client C decides to trust package P and package base. Then does
C trust module M? Well M is marked <option>-XTrustworthy</option>, so we
don't restrict the language. However, we still must check M's imports:
<itemizedlist>
<listitem>First, M imports System.IO.Unsafe. This is an unsafe module,
however M was compiled with <option>-XTrustworthy</option>, so P's
author takes responsibility for that import. C trusts P's author, so
this import is fine.
</listitem>
<listitem>
Second, M safe imports Buggle. For this import P's author takes no
responsibility for the safety, instead asking GHC to check whether
Buggle is trusted by C. Is it?
</listitem>
<listitem>
Buggle, is compiled with <option>-XSafe</option>, so the code is
machine-checked to be OK, but again under the assumption that all of
Buggle's imports are trusted by C. We must recursively check all
imports!
</listitem>
<liteitem>
Buggle only imports Prelude, which is compiled with
<option>-XTrustworthy</option>. Prelude resides in the base package,
which C trusts, and (we'll assume) all of Prelude's imports are
trusted. So C trusts Prelude, and so C also trusts Buggle. (While
Prelude is typically imported implicitly, it still obeys the same
rules outlined here).
</liteitem>
</itemizedlist>
</para>
<para>
Notice that C didn't need to trust package Wuggle; the machine checking
is enough. C only needs to trust packages that contain
<option>-XTrustworthy</option> modules.
</para>
</sect3>
<sect3 id="trustworthy-guarantees">
<title>Trustworthy Requirements</title>
<indexterm><primary>trustworthy</primary></indexterm>
Module authors using the <option>-XTrustworthy</option> language
extension for a module M should ensure that M's public API (the symbols
exposed by its export list) can't be used in an unsafe manner. This mean
that symbols exported should respect type safety and referential
transparency.
</sect3>
<sect3 id="safe-package-trust">
<title>Package Trust</title>
<indexterm><primary>package trust</primary></indexterm>
Safe Haskell gives packages a new Boolean property, that of trust.
Several new options are available at the GHC command-line to specify the
trust property of packages:
<itemizedlist>
<listitem><emphasis>-trust P</emphasis> — Exposes package P if it was
hidden and considers it a trusted package regardless of the package
database.</listitem>
<listitem><emphasis>-distrust P</emphasis> — Exposes package P if it
was hidden and considers it an untrusted package regardless of the
package database.</listitem>
<listitem><emphasis>-distrust-all-packages</emphasis> — Considers all
packages distrusted unless they are explicitly set to be trusted by
subsequent command-line options.</listitem>
</itemizedlist>
To set a package's trust property in the package database please refer to
<xref linkend="packages"/>.
</sect3>
</sect2>
<sect2 id="safe-inference">
<title>Safe Haskell Inference</title>
<indexterm><primary>safe inference</primary></indexterm>
<para>
In the case where a module is compiled without one of
<option>-XSafe</option>, <option>-XTrustworthy</option> or
<option>-XUnsafe</option> being used, GHC will try to figure out itself if
the module can be considered safe. This safety inference will never mark a
module as trustworthy, only as either unsafe or as safe. GHC uses a simple
method to determine this for a module M: If M would compile without error
under the <option>-XSafe</option> flag, then M is marked as safe.
Otherwise, it is marked as unsafe.
</para>
<para>
When should you use Safe Haskell inference and when should you use an
explicit <option>-XSafe</option> flag? The later case should be used when
you have a hard requirement that the module be safe. This is most useful
for the <xref linkend="safe-use-cases">security use case</xref> of Safe
Haskell: running untrusted code. Safe inference is meant to be used by
ordinary Haskell programmers. Users who probably don't care about Safe
Haskell.
</para>
<para>
Haskell library authors have a choice. Most should just use Safe inference.
Assuming you avoid any unsafe features of the language then your modules
will be marked safe. Inferred vs. Explicit has the following trade-offs:
</para>
<itemizedlist>
<listitem><emphasis>Inferred</emphasis> — This works well and adds no
dependencies on the Safe Haskell type of any modules in other packages.
It does mean that the Safe Haskell type of your own modules could
change without warning if a dependency changes. One way to deal with
this is through the use of <xref linkend="safe-flag-summary">Safe
Haskell warning flags</xref> that will warn if GHC infers a Safe
Haskell type different from expected.</listitem>
<listitem><emphasis>Explicit</emphasis> — This gives your library a
stable Safe Haskell type that others can depend on. However, it will
increase the chance of compilation failure when your package
dependencies change.</listitem>
</itemizedlist>
</sect2>
<sect2 id="safe-flag-summary">
<title>Safe Haskell Flag Summary</title>
<indexterm><primary>safe haskell flags</primary></indexterm>
In summary, Safe Haskell consists of the following three language flags:
<variablelist>
<varlistentry>
<term>-XSafe</term>
<indexterm><primary>-XSafe</primary></indexterm>
<listitem>Restricts the module to the safe language. All of the
module's direct imports must be trusted, but the module itself need
not reside in a trusted package, because the compiler vouches for its
trustworthiness. The "safe" keyword is allowed but meaningless in
import statements, as regardless, every import is required to be
safe.
<itemizedlist>
<listitem><emphasis>Module Trusted</emphasis> — Yes</listitem>
<listitem><emphasis>Haskell Language</emphasis> — Restricted to
Safe Language</listitem>
<listitem><emphasis>Imported Modules</emphasis> — All forced to be
safe imports, all must be trusted.</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>-XTrustworthy</term>
<indexterm><primary>-XTrustworthy</primary></indexterm>
<listitem>This establishes that the module is trusted, but the
guarantee is provided by the module's author. A client of this module
then specifies that they trust the module author by specifying they
trust the package containing the module.
<option>-XTrustworthy</option> doesn't restrict the module to the
safe language. It does however restrict the resolution of overlapping
instances to only allow <link linkend="safe-overlapping-instances">
safe overlapping instances</link>. It also allows the use of the safe
import keyword.
<itemizedlist>
<listitem><emphasis>Module Trusted</emphasis> — Yes.</listitem>
<listitem><emphasis>Module Trusted
(<option>-fpackage-trust</option> enabled)</emphasis> — Yes but
only if the package the module resides in is also
trusted.</listitem>
<listitem><emphasis>Haskell Language</emphasis> — Unrestricted,
except only <link linkend="safe-overlapping-instances">safe
overlapping instances</link> allowed.
</listitem>
<listitem><emphasis>Imported Modules</emphasis> — Under control of
module author which ones must be trusted.</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>-XUnsafe</term>
<indexterm><primary>-XUnsafe</primary></indexterm>
<listitem>Mark a module as unsafe so that it can't be imported by code
compiled with <option>-XSafe</option>. Also enable the Safe Import
extension so that a module can require a dependency to be trusted.
<itemizedlist>
<listitem><emphasis>Module Trusted</emphasis> — No</listitem>
<listitem><emphasis>Haskell Language</emphasis> —
Unrestricted</listitem>
<listitem><emphasis>Imported Modules</emphasis> — Under control of
module author which ones must be trusted.</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
And one general flag:
<variablelist>
<varlistentry>
<term>-fpackage-trust</term>
<indexterm><primary>-fpackage-trust</primary></indexterm>
<listitem>When enabled, turn on an extra check for a trustworthy module
M, requiring the package that M resides in be considered trusted, for
M to be considered trusted.
</listitem>
</varlistentry>
</variablelist>
And three warning flags:
<variablelist>
<varlistentry>
<term>-fwarn-unsafe</term>
<indexterm><primary>-fwarn-unsafe</primary></indexterm>
<listitem>Issue a warning if the module being compiled is regarded to
be unsafe. Should be used to check the safety type of modules when
using safe inference.
</listitem>
</varlistentry>
<varlistentry>
<term>-fwarn-safe</term>
<indexterm><primary>-fwarn-safe</primary></indexterm>
<listitem>Issue a warning if the module being compiled is regarded to
be safe. Should be used to check the safety type of modules when
using safe inference.
</listitem>
</varlistentry>
<varlistentry>
<term>-fwarn-trustworthy-safe</term>
<indexterm><primary>-fwarn-trustworthy-safe</primary></indexterm>
<listitem>Issue a warning if the module being compiled is marked as
<option>-XTrustworthy</option> but it could instead be marked as
<option>-XSafe</option>, a more informative bound. Can be used to
detect once a Safe Haskell bound can be improved as dependencies are
updated.</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="safe-compilation">
<title>Safe Compilation</title>
<indexterm><primary>safe compilation</primary></indexterm>
<para>
GHC includes a variety of flags that allow arbitrary processes to be run at
compilation time. One such example is the
<link linkend="pre-processor">custom pre-processor</link> flag. Another is
the ability of Template Haskell to execute Haskell code at compilation
time, including IO actions. Safe Haskell <emphasis>does not address this
danger</emphasis> (although, Template Haskell is a disallowed feature).
</para>
<para>
Due to this, it is suggested that when compiling untrusted source code that
has had no manual inspection done, the following precautions be taken:
<itemizedlist>
<listitem>Compile in a sandbox, such as a chroot or similar container
technology. Or simply as a user with very reduced system
access.</listitem>
<listitem>Compile untrusted code with the <option>-XSafe</option> flag
being specified on the command line. This will ensure that modifications
to the source being compiled can't disable the use of the Safe Language
as the command line flag takes precedence over a source level
pragma.</listitem>
<listitem>Ensure that all untrusted code is imported as a
<link linkend="safe-imports">safe import</link><emphasis> and</emphasis>
that the <link linkend="safe-package-trust"><option>-fpackage-trust</option></link>
flag is used with packages from untrusted sources being marked as
untrusted.</listitem>
</itemizedlist>
</para>
<para>
There is a more detailed discussion of the issues involved in compilation
safety and some potential solutions on the <ulink
url="http://ghc.haskell.org/trac/ghc/wiki/SafeHaskell/SafeCompilation">GHC
Wiki</ulink>.
</para>
</sect2>
</sect1>
<!-- Emacs stuff:
;;; Local Variables: ***
;;; sgml-parent-document: ("users_guide.xml" "book" "chapter" "sect1") ***
;;; End: ***
-->
|