• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "file_sharing/acl.h"
16 
17 #include <cerrno>
18 #include <new>
19 #include <type_traits>
20 #include "file_sharing/endian.h"
21 #include "securec.h"
22 
23 namespace OHOS {
24 namespace StorageDaemon {
ReCalcMaskPerm()25 ACL_PERM Acl::ReCalcMaskPerm()
26 {
27     ACL_PERM perm;
28     for (const auto &e : entries) {
29         if (e.tag == ACL_TAG::USER || e.tag == ACL_TAG::GROUP_OBJ || e.tag == ACL_TAG::GROUP) {
30             perm.Merge(e.perm);
31         }
32     }
33     return perm;
34 }
35 
IsEmpty()36 bool Acl::IsEmpty()
37 {
38     return entries.empty();
39 }
40 
IsValid()41 bool Acl::IsValid()
42 {
43     if (!entries.count(ACL_TAG::USER_OBJ) || !entries.count(ACL_TAG::GROUP_OBJ) ||
44             !entries.count(ACL_TAG::OTHER)) {
45         return false;
46     }
47     if (maskDemand && !entries.count(ACL_TAG::MASK)) {
48         return false;
49     }
50     return true;
51 }
52 
InsertEntry(const AclXattrEntry & entry)53 int Acl::InsertEntry(const AclXattrEntry &entry)
54 {
55     if (entries.size() >= ENTRIES_MAX_NUM) {
56         errno = EAGAIN;
57         return -1;
58     }
59 
60     switch (entry.tag) {
61         case ACL_TAG::GROUP_OBJ:
62         case ACL_TAG::USER_OBJ:
63         case ACL_TAG::MASK:
64         case ACL_TAG::OTHER:
65             entries.insert(entry);
66             break;
67         case ACL_TAG::USER:
68         case ACL_TAG::GROUP:
69             entries.insert(entry); // must before ReCalcMaskPerm()
70             maskDemand++;
71             /*
72              * In either case there's no or already one ACL_MASK entry in the set,
73              * we need to re-calculate MASK's permission and *insert* it (to replace
74              * the old one in latter case since we can't change std::set's element
75              * in-place). So do the following unconditionally.
76              *
77              * Be warned: do _NOT_ combine the following into one line, otherwise
78              * you can't pass the !!genius!! CI coding style check.
79              */
80             entries.insert(
81                 { ACL_TAG::MASK, ReCalcMaskPerm(), ACL_UNDEFINED_ID }
82             );
83             break;
84         default:
85             errno = EINVAL;
86             return -1;
87     }
88     return 0;
89 }
90 
Serialize(size_t & bufSize)91 char *Acl::Serialize(size_t &bufSize)
92 {
93     if (!IsValid()) {
94         errno = EINVAL;
95         return nullptr;
96     }
97 
98     /* clear possible previous allocation */
99     if (buf != nullptr) {
100         delete[] buf;
101         buf = nullptr;
102     }
103 
104     bufSize = sizeof(AclXattrHeader) + sizeof(AclXattrEntry) * entries.size();
105     if (bufSize > BUF_MAX_SIZE) {
106         bufSize = 0;
107         errno = EINVAL;
108         return nullptr;
109     }
110     buf = new (std::nothrow) char[bufSize];
111     if (buf == nullptr) {
112         errno = ENOMEM;
113         return nullptr;
114     }
115     auto err = memcpy_s(buf, bufSize, &header, sizeof(AclXattrHeader));
116     if (err != EOK) {
117         errno = err;
118         delete[] buf;
119         buf = nullptr;
120         return nullptr;
121     }
122 
123     size_t restSize = bufSize - sizeof(AclXattrHeader);
124     AclXattrEntry *ptr = reinterpret_cast<AclXattrEntry *>(buf + sizeof(AclXattrHeader));
125     for (const auto &e : entries) {
126         auto err = memcpy_s(ptr++, restSize, &e, sizeof(AclXattrEntry));
127         if (err != EOK) {
128             errno = err;
129             delete[] buf;
130             buf = nullptr;
131             return nullptr;
132         }
133         restSize -= sizeof(AclXattrEntry);
134     }
135     return buf;
136 }
137 
DeSerialize(const char * p,size_t size)138 int Acl::DeSerialize(const char *p, size_t size)
139 {
140     if (size > BUF_MAX_SIZE || size < sizeof(AclXattrHeader)) {
141         errno = EINVAL;
142         return -1;
143     }
144     header = *reinterpret_cast<const AclXattrHeader *>(p);
145     size -= sizeof(AclXattrHeader);
146     p += sizeof(AclXattrHeader);
147 
148     /*
149      * `e->tag != ACL_TAG::UNDEFINED` is unreliable outside the buffer, so check
150      * it after checking the size of remaining buffer.
151      */
152     for (const AclXattrEntry *e = reinterpret_cast<const AclXattrEntry *>(p);
153             size >= sizeof(AclXattrEntry) && LeToCpu(e->tag) != ACL_TAG::UNDEFINED;
154             e++) {
155         InsertEntry(*e);
156         size -= sizeof(AclXattrEntry);
157     }
158     if (size != 0) {
159         entries.clear();
160         header = { 0 };
161         errno = EINVAL;
162         return -1;
163     }
164 
165     return 0;
166 }
167 
~Acl()168 Acl::~Acl()
169 {
170     if (buf != nullptr) {
171         delete[] buf;
172         buf = nullptr;
173     }
174 }
175 } // STORAGE_DAEMON
176 } // OHOS
177