File: lite_fs.h

package info (click to toggle)
securefs 0.11.1%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,684 kB
  • sloc: cpp: 11,757; python: 486; sh: 11; makefile: 7
file content (169 lines) | stat: -rw-r--r-- 5,621 bytes parent folder | download
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
#pragma once

#include "crypto.h"
#include "lite_stream.h"
#include "mystring.h"
#include "myutils.h"
#include "platform.h"
#include "thread_safety_annotations.hpp"

#include <map>
#include <memory>
#include <mutex>
#include <string>

#include <cryptopp/aes.h>
#include <cryptopp/gcm.h>
#include <cryptopp/secblock.h>

namespace securefs
{
namespace lite
{
    class THREAD_ANNOTATION_CAPABILITY("mutex") File
    {
        DISABLE_COPY_MOVE(File)

    private:
        securefs::optional<lite::AESGCMCryptStream>
            m_crypt_stream THREAD_ANNOTATION_GUARDED_BY(*this);
        std::shared_ptr<securefs::FileStream> m_file_stream THREAD_ANNOTATION_GUARDED_BY(*this);
        std::mutex m_lock;

    public:
        explicit File(std::shared_ptr<securefs::FileStream> file_stream,
                      const key_type& master_key,
                      unsigned block_size,
                      unsigned iv_size,
                      bool check);
        ~File();

        length_type size() const THREAD_ANNOTATION_REQUIRES(*this)
        {
            return m_crypt_stream->size();
        }
        void flush() THREAD_ANNOTATION_REQUIRES(*this) { m_crypt_stream->flush(); }
        bool is_sparse() const noexcept THREAD_ANNOTATION_REQUIRES(*this)
        {
            return m_crypt_stream->is_sparse();
        }
        void resize(length_type len) THREAD_ANNOTATION_REQUIRES(*this)
        {
            m_crypt_stream->resize(len);
        }
        length_type read(void* output, offset_type off, length_type len)
            THREAD_ANNOTATION_REQUIRES(*this)
        {
            return m_crypt_stream->read(output, off, len);
        }
        void write(const void* input, offset_type off, length_type len)
            THREAD_ANNOTATION_REQUIRES(*this)
        {
            return m_crypt_stream->write(input, off, len);
        }
        void fstat(struct fuse_stat* stat) THREAD_ANNOTATION_REQUIRES(*this);
        void fsync() THREAD_ANNOTATION_REQUIRES(*this) { m_file_stream->fsync(); }
        void utimens(const fuse_timespec ts[2]) THREAD_ANNOTATION_REQUIRES(*this)
        {
            m_file_stream->utimens(ts);
        }
        void lock(bool exclusive = true) THREAD_ANNOTATION_ACQUIRE()
        {
            m_lock.lock();
            try
            {
                m_file_stream->lock(exclusive);
            }
            catch (...)
            {
                m_lock.unlock();
                throw;
            }
        }
        void unlock() noexcept THREAD_ANNOTATION_RELEASE()
        {
            m_file_stream->unlock();
            m_lock.unlock();
        }
    };

    class FileSystem;

    typedef std::unique_ptr<File> AutoClosedFile;

    std::string encrypt_path(AES_SIV& encryptor, StringRef path);
    std::string decrypt_path(AES_SIV& decryptor, StringRef path);

    class InvalidFilenameException : public VerificationException
    {
    private:
        std::string m_filename;

    public:
        explicit InvalidFilenameException(std::string filename) : m_filename(filename) {}
        ~InvalidFilenameException();

        std::string message() const override;
        int error_number() const noexcept override { return EINVAL; }
    };

    class FileSystem
    {
        DISABLE_COPY_MOVE(FileSystem)

    private:
        AES_SIV m_name_encryptor;
        key_type m_content_key;
        CryptoPP::GCM<CryptoPP::AES>::Encryption m_xattr_enc;
        CryptoPP::GCM<CryptoPP::AES>::Decryption m_xattr_dec;
        std::shared_ptr<const securefs::OSService> m_root;
        unsigned m_block_size, m_iv_size;
        unsigned m_flags;

    private:
        std::string translate_path(StringRef path, bool preserve_leading_slash);

    public:
        FileSystem(std::shared_ptr<const securefs::OSService> root,
                   const key_type& name_key,
                   const key_type& content_key,
                   const key_type& xattr_key,
                   unsigned block_size,
                   unsigned iv_size,
                   unsigned flags);

        ~FileSystem();

        AutoClosedFile open(StringRef path, int flags, fuse_mode_t mode);
        bool stat(StringRef path, struct fuse_stat* buf);
        void mkdir(StringRef path, fuse_mode_t mode);
        void rmdir(StringRef path);
        void chmod(StringRef path, fuse_mode_t mode);
        void chown(StringRef path, fuse_uid_t uid, fuse_gid_t gid);
        void rename(StringRef from, StringRef to);
        void unlink(StringRef path);
        void symlink(StringRef to, StringRef from);
        void link(StringRef src, StringRef dest);
        size_t readlink(StringRef path, char* buf, size_t size);
        void utimens(StringRef path, const fuse_timespec tm[2]);
        void statvfs(struct fuse_statvfs* buf);
        std::unique_ptr<DirectoryTraverser> create_traverser(StringRef path);

#ifdef __APPLE__
        // These APIs, unlike all others, report errors through negative error numbers as defined in
        // <errno.h>
        ssize_t listxattr(const char* path, char* buf, size_t size) noexcept
        {
            return m_root->listxattr(translate_path(path, false).c_str(), buf, size);
        }
        ssize_t getxattr(const char* path, const char* name, void* buf, size_t size) noexcept;
        int
        setxattr(const char* path, const char* name, void* buf, size_t size, int flags) noexcept;
        int removexattr(const char* path, const char* name) noexcept
        {
            return m_root->removexattr(translate_path(path, false).c_str(), name);
        }
#endif
    };
}    // namespace lite
}    // namespace securefs