├── .gitignore
├── LICENSE
├── README.md
├── build_ksu_module.sh
├── build_ksu_susfs_tool.sh
├── kernel_patches
├── 50_add_susfs_in_kernel-4.14.patch
├── 50_add_susfs_in_kernel-4.19.patch
├── 50_add_susfs_in_kernel-4.9.patch
├── 50_add_susfs_in_kernel-5.4.patch
├── KernelSU
│ └── 10_enable_susfs_for_ksu.patch
├── fs
│ └── susfs.c
└── include
│ └── linux
│ └── susfs.h
├── ksu_module_susfs
├── META-INF
│ └── com
│ │ └── google
│ │ └── android
│ │ ├── update-binary
│ │ └── updater-script
├── README.md
├── customize.sh
├── module.prop
├── post-fs-data.sh
├── service.sh
├── tools
│ ├── ksu_susfs_arm
│ └── ksu_susfs_arm64
└── uninstall.sh
└── ksu_susfs
└── jni
├── Android.mk
├── Application.mk
└── main.c
/.gitignore:
--------------------------------------------------------------------------------
1 | ksu_susfs/obj
2 | ksu_susfs/libs
3 | *.zip
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C) 2024 simonpunk
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C) 2024 simonpunk
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Important Notice] #
2 | _**Master repo will stay on version 1.3.8 forever, please refer to other branches for latest SUSFS code for different kernel version.**_
3 |
4 |
5 |
6 | # Introduction #
7 | An addon root hiding kernel patches and userspace module for KernelSU.
8 |
9 | The ksu_susfs userspace tool and ksu module requires a susfs patched kernel to work.
10 |
11 | # Warning #
12 | This is only experimental code, that said it can harm your system or cause performance hit, **YOU ARE !! W A R N E D !!** already
13 |
14 | ## Compatibility ##
15 | The susfs kernel patches may differ for different kernel version or even on the same kernel version, you may need to create your own patches for your kernel.
16 |
17 | ## Patch Instruction ##
18 | 1. Clone the repo with a tag that has release version, as tag with release version is more stable
19 | 2. Run `cp ./kernel_patches/KernelSU/10_enable_susfs_for_ksu.patch $KERNEL_ROOT/KernelSU/`
20 | 3. Run `cp ./kernel_patches/50_add_susfs_in_kernel-.patch $KERNEL_ROOT/`
21 | 4. Run `cp ./kernel_patches/fs/susfs.c $KERNEL_ROOT/fs/`
22 | 5. Run `cp ./kernel_patches/include/linux/susfs.h $KERNEL_ROOT/include/linux/`
23 | 6. Run `cd $KERNEL_ROOT/KernelSU` and then `patch -p1 < 10_enable_susfs_for_ksu.patch`
24 | 7. Run `cd $KERNEL_ROOT` and then `patch -p1 < 50_add_susfs_in_kernel.patch`, **if there are failed patches, you may try to patch them manually by yourself.**
25 | 8. Make sure again to have `CONFIG_KSU` and `CONFIG_KSU_SUSFS` enabled before building the kernel, some other SUSFS feature are disabled by default, you may turn it on via menuconfig or change it in your config file
26 | 9. Build and flash the kernel.
27 |
28 | ## Build ksu_susfs userspace tool ##
29 | 1. Run `./build_ksu_susfs_tool.sh` to build the userspace tool `ksu_susfs`, and the arm64 and arm binary will be copied to `ksu_module_susfs/tools/` as well.
30 | 2. Now you can also push the compiled `ksu_susfs` tool to `/data/adb/ksu/bin/` so that you can run it directly in adb root shell or termux root shell, as well as in your own ksu modules.
31 |
32 | ## Build ksu module ##
33 | The ksu module here is just a demo to show how to use it.
34 | It will also copy the ksu_susfs tool to `/data/adb/ksu/bin/` as well when installing the module.
35 |
36 | 1. ksu_susfs tool can be run in any stage scripts, post-fs-data.sh, services.sh, boot-completed.sh according to your own need.
37 | 2. Then run `./build_ksu_module.sh` to build the KernelSU module.
38 |
39 | ## Usage of ksu_susfs ##
40 | - Run ksu_susfs in root shell for usages.
41 |
42 | ## Known Issues ##
43 | - mnt_id_reorder feature causes bootloop for non-gki devices, more test is needed.
44 |
45 | ## Credits ##
46 | - KernelSU: https://github.com/tiann/KernelSU
47 | - @Kartatz: for ideas and original commit from https://github.com/Dominium-Apum/kernel_xiaomi_chime/pull/1/commits/74f8d4ecacd343432bb8137b7e7fbe3fd9fef189
48 |
49 | ## Telegram ##
50 | - @simonpunk
51 |
--------------------------------------------------------------------------------
/build_ksu_module.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | OUT_FILE=ksu_module_susfs.zip
4 | OLD_CWD=$(pwd)
5 |
6 | cd ksu_module_susfs && zip -r9 ../${OUT_FILE} * -x ${OUT_FILE}
7 |
8 | cd ${OLD_CWD}
9 |
--------------------------------------------------------------------------------
/build_ksu_susfs_tool.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | OLD_CWD=$(pwd)
4 |
5 | if ! ndk-build -s -v &>/dev/null; then
6 | echo "[-] Have you added the root directory of ndk-build to your PATH envoironment variable?"
7 | exit 1
8 | fi
9 |
10 | set -x
11 |
12 | cd ./ksu_susfs
13 | rm -rf libs obj 2>/dev/null
14 | ndk-build
15 | cp libs/arm64-v8a/ksu_susfs ../ksu_module_susfs/tools/ksu_susfs_arm64
16 | cp libs/armeabi-v7a/ksu_susfs ../ksu_module_susfs/tools/ksu_susfs_arm
17 | cd ${OLD_CWD}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/kernel_patches/50_add_susfs_in_kernel-4.14.patch:
--------------------------------------------------------------------------------
1 | diff --git a/fs/Makefile b/fs/Makefile
2 | index 0e97f4b85bee..5ef37c17ee91 100644
3 | --- a/fs/Makefile
4 | +++ b/fs/Makefile
5 | @@ -13,6 +13,8 @@ obj-y := open.o read_write.o file_table.o super.o \
6 | pnode.o splice.o sync.o utimes.o \
7 | stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
8 |
9 | +obj-$(CONFIG_KSU_SUSFS) += susfs.o
10 | +
11 | ifeq ($(CONFIG_BLOCK),y)
12 | obj-y += buffer.o block_dev.o direct-io.o mpage.o
13 | else
14 | diff --git a/fs/internal.h b/fs/internal.h
15 | index 3e58863de514..4fe0133cc4f6 100644
16 | --- a/fs/internal.h
17 | +++ b/fs/internal.h
18 | @@ -74,6 +74,10 @@ extern int __mnt_want_write_file(struct file *);
19 | extern void __mnt_drop_write(struct vfsmount *);
20 | extern void __mnt_drop_write_file(struct file *);
21 |
22 | +#ifdef CONFIG_KSU_SUSFS
23 | +int path_umount(struct path *path, int flags);
24 | +#endif
25 | +
26 | /*
27 | * fs_struct.c
28 | */
29 | diff --git a/fs/namei.c b/fs/namei.c
30 | index 0cbf8f5a92f4..2ff97f64a110 100644
31 | --- a/fs/namei.c
32 | +++ b/fs/namei.c
33 | @@ -42,6 +42,10 @@
34 | #include "internal.h"
35 | #include "mount.h"
36 |
37 | +#ifdef CONFIG_KSU_SUSFS
38 | +#include
39 | +#endif
40 | +
41 | /* [Feb-1997 T. Schoebel-Theuer]
42 | * Fundamental changes in the pathname lookup mechanisms (namei)
43 | * were necessary because of omirr. The reason is that omirr needs
44 | @@ -3619,6 +3623,13 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
45 | int flags = op->lookup_flags;
46 | struct file *filp;
47 |
48 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
49 | + int error;
50 | + if (susfs_sus_path_by_filename(pathname, &error, SYSCALL_FAMILY_ALL_ENOENT)) {
51 | + return ERR_PTR(error);
52 | + }
53 | +#endif
54 | +
55 | set_nameidata(&nd, dfd, pathname);
56 | filp = path_openat(&nd, op, flags | LOOKUP_RCU);
57 | if (unlikely(filp == ERR_PTR(-ECHILD)))
58 | @@ -3819,6 +3830,19 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
59 | int error;
60 | unsigned int lookup_flags = 0;
61 |
62 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
63 | + struct filename* fname;
64 | + int status;
65 | +
66 | + fname = getname_safe(filename);
67 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKNOD);
68 | + putname_safe(fname);
69 | +
70 | + if (status) {
71 | + return error;
72 | + }
73 | +#endif
74 | +
75 | error = may_mknod(mode);
76 | if (error)
77 | return error;
78 | @@ -3899,6 +3923,19 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
79 | int error;
80 | unsigned int lookup_flags = LOOKUP_DIRECTORY;
81 |
82 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
83 | + struct filename* fname;
84 | + int status;
85 | +
86 | + fname = getname_safe(pathname);
87 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKDIRAT);
88 | + putname_safe(fname);
89 | +
90 | + if (status) {
91 | + return error;
92 | + }
93 | +#endif
94 | +
95 | retry:
96 | dentry = user_path_create(dfd, pathname, &path, lookup_flags);
97 | if (IS_ERR(dentry))
98 | @@ -3976,6 +4013,21 @@ static long do_rmdir(int dfd, const char __user *pathname)
99 | struct qstr last;
100 | int type;
101 | unsigned int lookup_flags = 0;
102 | +
103 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
104 | + struct filename* fname;
105 | + int status;
106 | +
107 | + fname = getname_safe(pathname);
108 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RMDIR);
109 | + putname_safe(fname);
110 | +
111 | + if (status) {
112 | + return error;
113 | + }
114 | + error = 0;
115 | +#endif
116 | +
117 | retry:
118 | name = user_path_parent(dfd, pathname,
119 | &path, &last, &type, lookup_flags);
120 | @@ -4112,6 +4164,20 @@ static long do_unlinkat(int dfd, const char __user *pathname)
121 | struct inode *inode = NULL;
122 | struct inode *delegated_inode = NULL;
123 | unsigned int lookup_flags = 0;
124 | +
125 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
126 | + struct filename* fname;
127 | + int status;
128 | +
129 | + fname = getname_safe(pathname);
130 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_UNLINKAT);
131 | + putname_safe(fname);
132 | +
133 | + if (status) {
134 | + return error;
135 | + }
136 | +#endif
137 | +
138 | retry:
139 | name = user_path_parent(dfd, pathname,
140 | &path, &last, &type, lookup_flags);
141 | @@ -4226,6 +4292,19 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
142 | struct path path;
143 | unsigned int lookup_flags = 0;
144 |
145 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
146 | + struct filename* fname;
147 | + int status;
148 | +
149 | + fname = getname_safe(newname);
150 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_SYMLINKAT_NEWNAME);
151 | + putname_safe(fname);
152 | +
153 | + if (status) {
154 | + return error;
155 | + }
156 | +#endif
157 | +
158 | from = getname(oldname);
159 | if (IS_ERR(from))
160 | return PTR_ERR(from);
161 | @@ -4357,6 +4436,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
162 | int how = 0;
163 | int error;
164 |
165 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
166 | + struct filename* fname;
167 | + int status;
168 | +
169 | + fname = getname_safe(oldname);
170 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_OLDNAME);
171 | + putname_safe(fname);
172 | +
173 | + if (status) {
174 | + return error;
175 | + }
176 | +
177 | + fname = getname_safe(newname);
178 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_NEWNAME);
179 | + putname_safe(fname);
180 | +
181 | + if (status) {
182 | + return error;
183 | + }
184 | +#endif
185 | +
186 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
187 | return -EINVAL;
188 | /*
189 | @@ -4620,6 +4720,27 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
190 | bool should_retry = false;
191 | int error;
192 |
193 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
194 | + struct filename* fname;
195 | + int status;
196 | +
197 | + fname = getname_safe(oldname);
198 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_OLDNAME);
199 | + putname_safe(fname);
200 | +
201 | + if (status) {
202 | + return error;
203 | + }
204 | +
205 | + fname = getname_safe(newname);
206 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_NEWNAME);
207 | + putname_safe(fname);
208 | +
209 | + if (status) {
210 | + return error;
211 | + }
212 | +#endif
213 | +
214 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
215 | return -EINVAL;
216 |
217 | diff --git a/fs/open.c b/fs/open.c
218 | index 4d0c69bc056d6..73d4331494f85 100644
219 | --- a/fs/open.c
220 | +++ b/fs/open.c
221 | @@ -34,6 +34,10 @@
222 |
223 | #include "internal.h"
224 |
225 | +#ifdef CONFIG_KSU_SUSFS
226 | +#include
227 | +#endif
228 | +
229 | int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
230 | unsigned int time_attrs, struct file *filp)
231 | {
232 | @@ -140,6 +144,18 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
233 | unsigned int lookup_flags = LOOKUP_FOLLOW;
234 | struct path path;
235 | int error;
236 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
237 | + struct filename* fname;
238 | + int status;
239 | +
240 | + fname = getname_safe(pathname);
241 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
242 | + putname_safe(fname);
243 | +
244 | + if (status) {
245 | + return error;
246 | + }
247 | +#endif
248 |
249 | if (length < 0) /* sorry, but loff_t says... */
250 | return -EINVAL;
251 | @@ -373,10 +373,27 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
252 | struct vfsmount *mnt;
253 | int res;
254 | unsigned int lookup_flags = LOOKUP_FOLLOW;
255 | +
256 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
257 | + struct filename* fname;
258 | + int status;
259 | + int error;
260 | +#endif
261 | +
262 | #ifdef CONFIG_KSU
263 | ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
264 | #endif
265 |
266 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
267 | + fname = getname_safe(filename);
268 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
269 | + putname_safe(fname);
270 | +
271 | + if (status) {
272 | + return error;
273 | + }
274 | +#endif
275 | +
276 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
277 | return -EINVAL;
278 |
279 | @@ -466,6 +498,20 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename)
280 | struct path path;
281 | int error;
282 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
283 | +
284 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
285 | + struct filename* fname;
286 | + int status;
287 | +
288 | + fname = getname_safe(filename);
289 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
290 | + putname_safe(fname);
291 | +
292 | + if (status) {
293 | + return error;
294 | + }
295 | +#endif
296 | +
297 | retry:
298 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
299 | if (error)
300 | diff --git a/fs/proc/base.c b/fs/proc/base.c
301 | index b6959f6dae5b..9665ef85f778 100644
302 | --- a/fs/proc/base.c
303 | +++ b/fs/proc/base.c
304 | @@ -97,6 +97,10 @@
305 |
306 | #include "../../lib/kstrtox.h"
307 |
308 | +#ifdef CONFIG_KSU_SUSFS
309 | +#include
310 | +#endif
311 | +
312 | /* NOTE:
313 | * Implementing inode permission operations in /proc is almost
314 | * certainly an error. Permission checks need to happen during
315 | @@ -1828,6 +1832,15 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
316 | char *pathname;
317 | int len;
318 |
319 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
320 | + struct mm_struct *mm;
321 | + struct vm_area_struct *vma;
322 | + struct file *vma_file;
323 | + struct dentry *vma_dentry;
324 | + struct inode *vma_inode;
325 | + unsigned long ino;
326 | +#endif
327 | +
328 | if (!tmp)
329 | return -ENOMEM;
330 |
331 | @@ -1839,6 +1852,38 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
332 |
333 | if (len > buflen)
334 | len = buflen;
335 | +
336 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
337 | + if (!susfs_is_sus_proc_fd_link_list_empty()) {
338 | + if (susfs_sus_proc_fd_link(pathname, len))
339 | + goto orig_flow;
340 | + }
341 | +#endif
342 | +
343 | +
344 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
345 | + if (!susfs_is_sus_maps_list_empty()) {
346 | + mm = current->mm;
347 | + down_read(&mm->mmap_sem);
348 | + for (vma = mm->mmap; vma; vma = vma->vm_next) {
349 | + if (vma->vm_file) {
350 | + vma_file = vma->vm_file;
351 | + vma_dentry = vma_file->f_path.dentry;
352 | + if (vma_dentry == path->dentry) {
353 | + vma_inode = file_inode(vma_file);
354 | + ino = vma_inode->i_ino;
355 | + susfs_sus_map_files_readlink(ino, pathname);
356 | + break;
357 | + }
358 | + }
359 | + }
360 | + up_read(&mm->mmap_sem);
361 | + }
362 | +#endif
363 | +
364 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
365 | +orig_flow:
366 | +#endif
367 | if (copy_to_user(buffer, pathname, len))
368 | len = -EFAULT;
369 | out:
370 | @@ -2207,6 +2252,9 @@ struct map_files_info {
371 | fmode_t mode;
372 | unsigned long len;
373 | unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
374 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
375 | + int susfs_action;
376 | +#endif
377 | };
378 |
379 | /*
380 | @@ -2269,6 +2317,10 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
381 | int result;
382 | struct mm_struct *mm;
383 |
384 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
385 | + int ret = 0;
386 | +#endif
387 | +
388 | result = -ENOENT;
389 | task = get_proc_task(dir);
390 | if (!task)
391 | @@ -2291,6 +2343,23 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
392 | if (!vma)
393 | goto out_no_vma;
394 |
395 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
396 | + if (vma->vm_file) {
397 | + ret = susfs_sus_map_files_instantiate(vma);
398 | + if (ret == 1) {
399 | + if (vma->vm_file->f_mode & FMODE_WRITE) {
400 | + vma->vm_file->f_mode &= ~FMODE_WRITE;
401 | + }
402 | + goto orig_flow;
403 | + }
404 | + if (ret == 2) {
405 | + result = -ENOENT;
406 | + goto out_no_vma;
407 | + }
408 | + }
409 | +orig_flow:
410 | +#endif
411 | +
412 | if (vma->vm_file)
413 | result = proc_map_files_instantiate(dir, dentry, task,
414 | (void *)(unsigned long)vma->vm_file->f_mode);
415 | @@ -2322,6 +2391,10 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
416 | struct map_files_info *p;
417 | int ret;
418 |
419 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
420 | + int susfs_ret = 0;
421 | +#endif
422 | +
423 | ret = -ENOENT;
424 | task = get_proc_task(file_inode(file));
425 | if (!task)
426 | @@ -2380,6 +2453,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
427 | info.len = snprintf(info.name,
428 | sizeof(info.name), "%lx-%lx",
429 | vma->vm_start, vma->vm_end);
430 | +
431 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
432 | + susfs_ret = susfs_sus_map_files_instantiate(vma);
433 | + info.susfs_action = susfs_ret;
434 | +#endif
435 | +
436 | if (flex_array_put(fa, i++, &info, GFP_KERNEL))
437 | BUG();
438 | }
439 | @@ -2388,12 +2467,28 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
440 |
441 | for (i = 0; i < nr_files; i++) {
442 | p = flex_array_get(fa, i);
443 | +
444 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
445 | + if (p->susfs_action == SUSFS_MAP_FILES_ACTION_REMOVE_WRITE_PERM) {
446 | + if (p->mode & FMODE_WRITE) {
447 | + p->mode &= ~FMODE_WRITE;
448 | + }
449 | + } else if (p->susfs_action == SUSFS_MAP_FILES_ACTION_HIDE_DENTRY) {
450 | + goto skip_proc_fill_cache;
451 | + }
452 | +#endif
453 | +
454 | if (!proc_fill_cache(file, ctx,
455 | p->name, p->len,
456 | proc_map_files_instantiate,
457 | task,
458 | (void *)(unsigned long)p->mode))
459 | break;
460 | +
461 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
462 | +skip_proc_fill_cache:
463 | +#endif
464 | +
465 | ctx->pos++;
466 | }
467 | if (fa)
468 | diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
469 | index 006a327032078..0b7c0162dad7b 100644
470 | --- a/fs/proc/task_mmu.c
471 | +++ b/fs/proc/task_mmu.c
472 | @@ -24,6 +24,10 @@
473 | #include
474 | #include "internal.h"
475 |
476 | +#ifdef CONFIG_KSU_SUSFS
477 | +#include
478 | +#endif
479 | +
480 | void task_mem(struct seq_file *m, struct mm_struct *mm)
481 | {
482 | unsigned long text, lib, swap, ptes, pmds, anon, file, shmem;
483 | @@ -460,6 +464,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
484 | unsigned long start, end;
485 | dev_t dev = 0;
486 | const char *name = NULL;
487 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
488 | + char *out_name;
489 | + int ret = 0;
490 | +#endif
491 |
492 | if (file) {
493 | struct inode *inode = file_inode(vma->vm_file);
494 | @@ -475,6 +475,26 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
495 | start = vma->vm_start;
496 | end = vma->vm_end;
497 |
498 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
499 | + out_name = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
500 | + if (!out_name)
501 | + goto orig_flow;
502 | + ret = susfs_sus_maps(ino, end - start, &ino, &dev, &flags, &pgoff, vma, out_name);
503 | +
504 | +orig_flow:
505 | +#endif
506 | +
507 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
508 | + if (ret == 2) {
509 | + seq_pad(m, ' ');
510 | + seq_puts(m, out_name);
511 | + seq_putc(m, '\n');
512 | + kfree(out_name);
513 | + return;
514 | + }
515 | + kfree(out_name);
516 | +#endif
517 | +
518 | /*
519 | * Print the dentry name for named mappings, and a
520 | * special [heap] marker for the heap:
521 | diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
522 | index 6863773aff25..493de1b4e7de 100644
523 | --- a/fs/proc_namespace.c
524 | +++ b/fs/proc_namespace.c
525 | @@ -15,6 +15,10 @@
526 | #include "pnode.h"
527 | #include "internal.h"
528 |
529 | +#ifdef CONFIG_KSU_SUSFS
530 | +#include
531 | +#endif
532 | +
533 | static unsigned mounts_poll(struct file *file, poll_table *wait)
534 | {
535 | struct seq_file *m = file->private_data;
536 | @@ -99,6 +103,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
537 | struct super_block *sb = mnt_path.dentry->d_sb;
538 | int err;
539 |
540 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
541 | + if (susfs_sus_mount(mnt, &p->root))
542 | + return SEQ_SKIP;
543 | +#endif
544 | +
545 | if (sb->s_op->show_devname) {
546 | err = sb->s_op->show_devname(m, mnt_path.dentry);
547 | if (err)
548 | @@ -135,8 +144,30 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
549 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
550 | int err;
551 |
552 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
553 | + int out_mnt_id = 0, out_parent_mnt_id = 0;
554 | + int status = 1;
555 | +#endif
556 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
557 | + if (susfs_sus_mount(mnt, &p->root))
558 | + return 0;
559 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
560 | + if (!uid_matches_proc_need_to_reorder_mnt_id())
561 | + goto orig_flow;
562 | + status = susfs_get_fake_mnt_id(r->mnt_id, &out_mnt_id, &out_parent_mnt_id);
563 | + if (status)
564 | + goto orig_flow;
565 | + seq_printf(m, "%i %i %u:%u ", out_mnt_id, out_parent_mnt_id,
566 | + MAJOR(sb->s_dev), MINOR(sb->s_dev));
567 | + goto bypass_orig_flow;
568 | +orig_flow:
569 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
570 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
571 | seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
572 | MAJOR(sb->s_dev), MINOR(sb->s_dev));
573 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
574 | +bypass_orig_flow:
575 | +#endif
576 | if (sb->s_op->show_path) {
577 | err = sb->s_op->show_path(m, mnt->mnt_root);
578 | if (err)
579 | @@ -199,6 +230,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
580 | struct super_block *sb = mnt_path.dentry->d_sb;
581 | int err;
582 |
583 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
584 | + if (susfs_sus_mount(mnt, &p->root))
585 | + return 0;
586 | +#endif
587 | +
588 | /* device */
589 | if (sb->s_op->show_devname) {
590 | seq_puts(m, "device ");
591 | @@ -282,6 +318,12 @@ static int mounts_open_common(struct inode *inode, struct file *file,
592 | p->show = show;
593 | p->cached_event = ~0ULL;
594 |
595 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
596 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
597 | + susfs_add_mnt_id_recorder(p->ns);
598 | + }
599 | +#endif
600 | +
601 | return 0;
602 |
603 | err_put_path:
604 | @@ -296,6 +338,13 @@ static int mounts_release(struct inode *inode, struct file *file)
605 | {
606 | struct seq_file *m = file->private_data;
607 | struct proc_mounts *p = m->private;
608 | +
609 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
610 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
611 | + susfs_remove_mnt_id_recorder();
612 | + }
613 | +#endif
614 | +
615 | path_put(&p->root);
616 | put_mnt_ns(p->ns);
617 | return seq_release_private(inode, file);
618 | diff --git a/fs/readdir.c b/fs/readdir.c
619 | index 1059f2a9be0b..41e5677c178d 100644
620 | --- a/fs/readdir.c
621 | +++ b/fs/readdir.c
622 | @@ -21,6 +21,10 @@
623 |
624 | #include
625 |
626 | +#ifdef CONFIG_KSU_SUSFS
627 | +#include
628 | +#endif
629 | +
630 | int iterate_dir(struct file *file, struct dir_context *ctx)
631 | {
632 | struct inode *inode = file_inode(file);
633 | @@ -305,6 +309,11 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
634 | if (dirent) {
635 | if (signal_pending(current))
636 | return -EINTR;
637 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
638 | + if (susfs_sus_ino_for_filldir64(ino)) {
639 | + return 0;
640 | + }
641 | +#endif
642 | if (__put_user(offset, &dirent->d_off))
643 | goto efault;
644 | }
645 | diff --git a/fs/stat.c b/fs/stat.c
646 | index 0fda4b6b8fb2a..5c0bb294b10a7 100644
647 | --- a/fs/stat.c
648 | +++ b/fs/stat.c
649 | @@ -21,6 +21,10 @@
650 | #include
651 | #include
652 |
653 | +#ifdef CONFIG_KSU_SUSFS
654 | +#include
655 | +#endif
656 | +
657 | /**
658 | * generic_fillattr - Fill in the basic attributes from the inode struct
659 | * @inode: Inode to use as the source
660 | @@ -110,6 +114,12 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
661 | {
662 | int retval;
663 |
664 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
665 | + if (susfs_sus_path_by_path(path, &retval, SYSCALL_FAMILY_ALL_ENOENT)) {
666 | + return retval;
667 | + }
668 | +#endif
669 | +
670 | retval = security_inode_getattr(path);
671 | if (retval)
672 | return retval;
673 | @@ -326,6 +336,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
674 | #endif
675 | tmp.st_blocks = stat->blocks;
676 | tmp.st_blksize = stat->blksize;
677 | +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
678 | + susfs_sus_kstat(tmp.st_ino, &tmp);
679 | +#endif
680 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
681 | }
682 |
683 | diff --git a/kernel/sys.c b/kernel/sys.c
684 | index a7f823224546..893b17bf71c6 100644
685 | --- a/kernel/sys.c
686 | +++ b/kernel/sys.c
687 | @@ -66,6 +66,10 @@
688 | #include
689 | #include
690 |
691 | +#ifdef CONFIG_KSU_SUSFS
692 | +#include
693 | +#endif
694 | +
695 | #ifndef SET_UNALIGN_CTL
696 | # define SET_UNALIGN_CTL(a, b) (-EINVAL)
697 | #endif
698 | @@ -1150,6 +1154,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
699 | down_read(&uts_sem);
700 | memcpy(&tmp, utsname(), sizeof(tmp));
701 | up_read(&uts_sem);
702 | +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
703 | + susfs_spoof_uname(&tmp);
704 | +#endif
705 | if (copy_to_user(name, &tmp, sizeof(tmp)))
706 | return -EFAULT;
707 |
708 | diff --git a/mm/shmem.c b/mm/shmem.c
709 | index a26c9dd68452c..ce2970f16f11b 100644
710 | --- a/mm/shmem.c
711 | +++ b/mm/shmem.c
712 | @@ -36,6 +36,10 @@
713 | #include
714 | #include
715 |
716 | +#ifdef CONFIG_KSU_SUSFS
717 | +#include
718 | +#endif
719 | +
720 | #include /* for arch/microblaze update_mmu_cache() */
721 |
722 | static struct vfsmount *shm_mnt;
723 | @@ -3791,6 +3795,13 @@ SYSCALL_DEFINE2(memfd_create,
724 | goto err_name;
725 | }
726 |
727 | +#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
728 | + if (susfs_sus_memfd(name)) {
729 | + error = -EFAULT;
730 | + goto err_name;
731 | + }
732 | +#endif
733 | +
734 | fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0);
735 | if (fd < 0) {
736 | error = fd;
737 |
--------------------------------------------------------------------------------
/kernel_patches/50_add_susfs_in_kernel-4.19.patch:
--------------------------------------------------------------------------------
1 | diff --git a/fs/Makefile b/fs/Makefile
2 | index 792e3acc1b65..5c6fa99af9a1 100644
3 | --- a/fs/Makefile
4 | +++ b/fs/Makefile
5 | @@ -14,6 +14,8 @@ obj-y := open.o read_write.o file_table.o super.o \
6 | pnode.o splice.o sync.o utimes.o d_path.o \
7 | stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
8 |
9 | +obj-$(CONFIG_KSU_SUSFS) += susfs.o
10 | +
11 | ifeq ($(CONFIG_BLOCK),y)
12 | obj-y += buffer.o block_dev.o direct-io.o mpage.o
13 | else
14 | diff --git a/fs/internal.h b/fs/internal.h
15 | index a47590445ca3..b8dd2218bbfe 100644
16 | --- a/fs/internal.h
17 | +++ b/fs/internal.h
18 | @@ -89,6 +89,10 @@ extern void __init mnt_init(void);
19 | extern int __mnt_want_write_file(struct file *);
20 | extern void __mnt_drop_write_file(struct file *);
21 |
22 | +#ifdef CONFIG_KSU_SUSFS
23 | +int path_umount(struct path *path, int flags);
24 | +#endif
25 | +
26 | /*
27 | * fs_struct.c
28 | */
29 | diff --git a/fs/namei.c b/fs/namei.c
30 | index 6f125a024cd7..92a35663377c 100644
31 | --- a/fs/namei.c
32 | +++ b/fs/namei.c
33 | @@ -51,6 +51,10 @@
34 | #define CREATE_TRACE_POINTS
35 | #include
36 |
37 | +#ifdef CONFIG_KSU_SUSFS
38 | +#include
39 | +#endif
40 | +
41 | /* [Feb-1997 T. Schoebel-Theuer]
42 | * Fundamental changes in the pathname lookup mechanisms (namei)
43 | * were necessary because of omirr. The reason is that omirr needs
44 | @@ -3733,6 +3737,13 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
45 | int flags = op->lookup_flags;
46 | struct file *filp;
47 |
48 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
49 | + int error;
50 | + if (susfs_sus_path_by_filename(pathname, &error, SYSCALL_FAMILY_ALL_ENOENT)) {
51 | + return ERR_PTR(error);
52 | + }
53 | +#endif
54 | +
55 | set_nameidata(&nd, dfd, pathname);
56 | filp = path_openat(&nd, op, flags | LOOKUP_RCU);
57 | if (unlikely(filp == ERR_PTR(-ECHILD)))
58 | @@ -3926,6 +3937,19 @@ long do_mknodat(int dfd, const char __user *filename, umode_t mode,
59 | int error;
60 | unsigned int lookup_flags = 0;
61 |
62 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
63 | + struct filename* fname;
64 | + int status;
65 | +
66 | + fname = getname_safe(filename);
67 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKNOD);
68 | + putname_safe(fname);
69 | +
70 | + if (status) {
71 | + return error;
72 | + }
73 | +#endif
74 | +
75 | error = may_mknod(mode);
76 | if (error)
77 | return error;
78 | @@ -4012,6 +4036,19 @@ long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
79 | int error;
80 | unsigned int lookup_flags = LOOKUP_DIRECTORY;
81 |
82 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
83 | + struct filename* fname;
84 | + int status;
85 | +
86 | + fname = getname_safe(pathname);
87 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKDIRAT);
88 | + putname_safe(fname);
89 | +
90 | + if (status) {
91 | + return error;
92 | + }
93 | +#endif
94 | +
95 | retry:
96 | dentry = user_path_create(dfd, pathname, &path, lookup_flags);
97 | if (IS_ERR(dentry))
98 | @@ -4100,6 +4137,21 @@ long do_rmdir(int dfd, const char __user *pathname)
99 | struct qstr last;
100 | int type;
101 | unsigned int lookup_flags = 0;
102 | +
103 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
104 | + struct filename* fname;
105 | + int status;
106 | +
107 | + fname = getname_safe(pathname);
108 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RMDIR);
109 | + putname_safe(fname);
110 | +
111 | + if (status) {
112 | + return error;
113 | + }
114 | + error = 0;
115 | +#endif
116 | +
117 | retry:
118 | name = filename_parentat(dfd, getname(pathname), lookup_flags,
119 | &path, &last, &type);
120 | @@ -4239,6 +4291,17 @@ long do_unlinkat(int dfd, struct filename *name)
121 | struct inode *inode = NULL;
122 | struct inode *delegated_inode = NULL;
123 | unsigned int lookup_flags = 0;
124 | +
125 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
126 | + int status;
127 | +
128 | + status = susfs_sus_path_by_filename(name, &error, SYSCALL_FAMILY_UNLINKAT);
129 | +
130 | + if (status) {
131 | + return error;
132 | + }
133 | +#endif
134 | +
135 | retry:
136 | name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type);
137 | if (IS_ERR(name))
138 | @@ -4356,6 +4419,19 @@ long do_symlinkat(const char __user *oldname, int newdfd,
139 | struct path path;
140 | unsigned int lookup_flags = 0;
141 |
142 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
143 | + struct filename* fname;
144 | + int status;
145 | +
146 | + fname = getname_safe(newname);
147 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_SYMLINKAT_NEWNAME);
148 | + putname_safe(fname);
149 | +
150 | + if (status) {
151 | + return error;
152 | + }
153 | +#endif
154 | +
155 | from = getname(oldname);
156 | if (IS_ERR(from))
157 | return PTR_ERR(from);
158 | @@ -4493,6 +4569,27 @@ int do_linkat(int olddfd, const char __user *oldname, int newdfd,
159 | int how = 0;
160 | int error;
161 |
162 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
163 | + struct filename* fname;
164 | + int status;
165 | +
166 | + fname = getname_safe(oldname);
167 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_OLDNAME);
168 | + putname_safe(fname);
169 | +
170 | + if (status) {
171 | + return error;
172 | + }
173 | +
174 | + fname = getname_safe(newname);
175 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_NEWNAME);
176 | + putname_safe(fname);
177 | +
178 | + if (status) {
179 | + return error;
180 | + }
181 | +#endif
182 | +
183 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
184 | return -EINVAL;
185 | /*
186 | @@ -4768,6 +4865,27 @@ static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
187 | bool should_retry = false;
188 | int error;
189 |
190 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
191 | + struct filename* fname;
192 | + int status;
193 | +
194 | + fname = getname_safe(oldname);
195 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_OLDNAME);
196 | + putname_safe(fname);
197 | +
198 | + if (status) {
199 | + return error;
200 | + }
201 | +
202 | + fname = getname_safe(newname);
203 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_NEWNAME);
204 | + putname_safe(fname);
205 | +
206 | + if (status) {
207 | + return error;
208 | + }
209 | +#endif
210 | +
211 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
212 | return -EINVAL;
213 |
214 | diff --git a/fs/open.c b/fs/open.c
215 | index a9166a454e56..5744591fd631 100644
216 | --- a/fs/open.c
217 | +++ b/fs/open.c
218 | @@ -38,6 +38,10 @@
219 | #include
220 | #endif
221 |
222 | +#ifdef CONFIG_KSU_SUSFS
223 | +#include
224 | +#endif
225 | +
226 | int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
227 | unsigned int time_attrs, struct file *filp)
228 | {
229 | @@ -133,6 +137,18 @@ long do_sys_truncate(const char __user *pathname, loff_t length)
230 | unsigned int lookup_flags = LOOKUP_FOLLOW;
231 | struct path path;
232 | int error;
233 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
234 | + struct filename* fname;
235 | + int status;
236 | +
237 | + fname = getname_safe(pathname);
238 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
239 | + putname_safe(fname);
240 | +
241 | + if (status) {
242 | + return error;
243 | + }
244 | +#endif
245 |
246 | if (length < 0) /* sorry, but loff_t says... */
247 | return -EINVAL;
248 | @@ -370,10 +386,27 @@ long do_faccessat(int dfd, const char __user *filename, int mode)
249 | struct vfsmount *mnt;
250 | int res;
251 | unsigned int lookup_flags = LOOKUP_FOLLOW;
252 | +
253 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
254 | + struct filename* fname;
255 | + int status;
256 | + int error;
257 | +#endif
258 | +
259 | #ifdef CONFIG_KSU
260 | ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
261 | #endif
262 |
263 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
264 | + fname = getname_safe(filename);
265 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
266 | + putname_safe(fname);
267 | +
268 | + if (status) {
269 | + return error;
270 | + }
271 | +#endif
272 | +
273 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
274 | return -EINVAL;
275 |
276 | @@ -476,6 +509,20 @@ int ksys_chdir(const char __user *filename)
277 | struct path path;
278 | int error;
279 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
280 | +
281 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
282 | + struct filename* fname;
283 | + int status;
284 | +
285 | + fname = getname_safe(filename);
286 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
287 | + putname_safe(fname);
288 | +
289 | + if (status) {
290 | + return error;
291 | + }
292 | +#endif
293 | +
294 | retry:
295 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
296 | if (error)
297 | diff --git a/fs/proc/base.c b/fs/proc/base.c
298 | index dac496048697..1a96a4ac38a9 100644
299 | --- a/fs/proc/base.c
300 | +++ b/fs/proc/base.c
301 | @@ -106,6 +106,10 @@
302 | #include
303 | #endif
304 |
305 | +#ifdef CONFIG_KSU_SUSFS
306 | +#include
307 | +#endif
308 | +
309 | /* NOTE:
310 | * Implementing inode permission operations in /proc is almost
311 | * certainly an error. Permission checks need to happen during
312 | @@ -1945,6 +1949,16 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
313 | char *pathname;
314 | int len;
315 |
316 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
317 | + struct mm_struct *mm;
318 | + struct vm_area_struct *vma;
319 | + struct file *vma_file;
320 | + struct dentry *vma_dentry;
321 | + struct inode *vma_inode;
322 | + unsigned long ino;
323 | +#endif
324 | +
325 | +
326 | if (!tmp)
327 | return -ENOMEM;
328 |
329 | @@ -1956,6 +1970,38 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
330 |
331 | if (len > buflen)
332 | len = buflen;
333 | +
334 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
335 | + if (!susfs_is_sus_proc_fd_link_list_empty()) {
336 | + if (susfs_sus_proc_fd_link(pathname, len))
337 | + goto orig_flow;
338 | + }
339 | +#endif
340 | +
341 | +
342 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
343 | + if (!susfs_is_sus_maps_list_empty()) {
344 | + mm = current->mm;
345 | + down_read(&mm->mmap_sem);
346 | + for (vma = mm->mmap; vma; vma = vma->vm_next) {
347 | + if (vma->vm_file) {
348 | + vma_file = vma->vm_file;
349 | + vma_dentry = vma_file->f_path.dentry;
350 | + if (vma_dentry == path->dentry) {
351 | + vma_inode = file_inode(vma_file);
352 | + ino = vma_inode->i_ino;
353 | + susfs_sus_map_files_readlink(ino, pathname);
354 | + break;
355 | + }
356 | + }
357 | + }
358 | + up_read(&mm->mmap_sem);
359 | + }
360 | +#endif
361 | +
362 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
363 | +orig_flow:
364 | +#endif
365 | if (copy_to_user(buffer, pathname, len))
366 | len = -EFAULT;
367 | out:
368 | @@ -2360,6 +2406,10 @@ struct map_files_info {
369 | unsigned long start;
370 | unsigned long end;
371 | fmode_t mode;
372 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
373 | + int susfs_action;
374 | +#endif
375 | +
376 | };
377 |
378 | /*
379 | @@ -2420,6 +2470,10 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
380 | struct dentry *result;
381 | struct mm_struct *mm;
382 |
383 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
384 | + int ret = 0;
385 | +#endif
386 | +
387 | result = ERR_PTR(-ENOENT);
388 | task = get_proc_task(dir);
389 | if (!task)
390 | @@ -2446,6 +2500,23 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
391 | if (!vma)
392 | goto out_no_vma;
393 |
394 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
395 | + if (vma->vm_file) {
396 | + ret = susfs_sus_map_files_instantiate(vma);
397 | + if (ret == 1) {
398 | + if (vma->vm_file->f_mode & FMODE_WRITE) {
399 | + vma->vm_file->f_mode &= ~FMODE_WRITE;
400 | + }
401 | + goto orig_flow;
402 | + }
403 | + if (ret == 2) {
404 | + result = ERR_PTR(-ENOENT);
405 | + goto out_no_vma;
406 | + }
407 | + }
408 | +orig_flow:
409 | +#endif
410 | +
411 | if (vma->vm_file)
412 | result = proc_map_files_instantiate(dentry, task,
413 | (void *)(unsigned long)vma->vm_file->f_mode);
414 | @@ -2478,6 +2549,10 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
415 | struct map_files_info *p;
416 | int ret;
417 |
418 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
419 | + int susfs_ret = 0;
420 | +#endif
421 | +
422 | ret = -ENOENT;
423 | task = get_proc_task(file_inode(file));
424 | if (!task)
425 | @@ -2540,6 +2615,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
426 | info.start = vma->vm_start;
427 | info.end = vma->vm_end;
428 | info.mode = vma->vm_file->f_mode;
429 | +
430 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
431 | + susfs_ret = susfs_sus_map_files_instantiate(vma);
432 | + info.susfs_action = susfs_ret;
433 | +#endif
434 | +
435 | if (flex_array_put(fa, i++, &info, GFP_KERNEL))
436 | BUG();
437 | }
438 | @@ -2553,12 +2634,28 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
439 |
440 | p = flex_array_get(fa, i);
441 | len = snprintf(buf, sizeof(buf), "%lx-%lx", p->start, p->end);
442 | +
443 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
444 | + if (p->susfs_action == SUSFS_MAP_FILES_ACTION_REMOVE_WRITE_PERM) {
445 | + if (p->mode & FMODE_WRITE) {
446 | + p->mode &= ~FMODE_WRITE;
447 | + }
448 | + } else if (p->susfs_action == SUSFS_MAP_FILES_ACTION_HIDE_DENTRY) {
449 | + goto skip_proc_fill_cache;
450 | + }
451 | +#endif
452 | +
453 | if (!proc_fill_cache(file, ctx,
454 | buf, len,
455 | proc_map_files_instantiate,
456 | task,
457 | (void *)(unsigned long)p->mode))
458 | break;
459 | +
460 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
461 | +skip_proc_fill_cache:
462 | +#endif
463 | +
464 | ctx->pos++;
465 | }
466 | if (fa)
467 | diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
468 | index 0e06632c4e3a..d21c25756e60 100644
469 | --- a/fs/proc/task_mmu.c
470 | +++ b/fs/proc/task_mmu.c
471 | @@ -28,6 +28,10 @@
472 | #include
473 | #include "internal.h"
474 |
475 | +#ifdef CONFIG_KSU_SUSFS
476 | +#include
477 | +#endif
478 | +
479 | #ifdef CONFIG_ZRAM_LRU_WRITEBACK
480 | #include
481 | #include "../../drivers/block/zram/zram_drv.h"
482 | @@ -387,6 +391,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
483 | unsigned long start, end;
484 | dev_t dev = 0;
485 | const char *name = NULL;
486 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
487 | + char *out_name;
488 | + int ret = 0;
489 | +#endif
490 |
491 | if (file) {
492 | struct inode *inode = file_inode(vma->vm_file);
493 | @@ -397,8 +405,28 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
494 |
495 | start = vma->vm_start;
496 | end = vma->vm_end;
497 | +
498 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
499 | + out_name = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
500 | + if (!out_name)
501 | + goto orig_flow;
502 | + ret = susfs_sus_maps(ino, end - start, &ino, &dev, &flags, &pgoff, vma, out_name);
503 | +
504 | +orig_flow:
505 | +#endif
506 | +
507 | show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);
508 |
509 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
510 | + if (ret == 2) {
511 | + seq_pad(m, ' ');
512 | + seq_puts(m, out_name);
513 | + seq_putc(m, '\n');
514 | + kfree(out_name);
515 | + return;
516 | + }
517 | + kfree(out_name);
518 | +#endif
519 | /*
520 | * Print the dentry name for named mappings, and a
521 | * special [heap] marker for the heap:
522 | diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
523 | index bd07f0f4f06b..7807ac16aecb 100644
524 | --- a/fs/proc_namespace.c
525 | +++ b/fs/proc_namespace.c
526 | @@ -18,6 +18,11 @@
527 | #include "pnode.h"
528 | #include "internal.h"
529 |
530 | +#ifdef CONFIG_KSU_SUSFS
531 | +#include
532 | +#endif
533 | +
534 | +
535 | static __poll_t mounts_poll(struct file *file, poll_table *wait)
536 | {
537 | struct seq_file *m = file->private_data;
538 | @@ -102,6 +107,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
539 | struct super_block *sb = mnt_path.dentry->d_sb;
540 | int err;
541 |
542 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
543 | + if (susfs_sus_mount(mnt, &p->root))
544 | + return 0;
545 | +#endif
546 | +
547 | if (sb->s_op->show_devname) {
548 | err = sb->s_op->show_devname(m, mnt_path.dentry);
549 | if (err)
550 | @@ -138,8 +148,31 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
551 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
552 | int err;
553 |
554 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
555 | + int out_mnt_id = 0, out_parent_mnt_id = 0;
556 | + int status = 1;
557 | +#endif
558 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
559 | + if (susfs_sus_mount(mnt, &p->root))
560 | + return 0;
561 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
562 | + if (!uid_matches_proc_need_to_reorder_mnt_id())
563 | + goto orig_flow;
564 | + status = susfs_get_fake_mnt_id(r->mnt_id, &out_mnt_id, &out_parent_mnt_id);
565 | + if (status)
566 | + goto orig_flow;
567 | + seq_printf(m, "%i %i %u:%u ", out_mnt_id, out_parent_mnt_id,
568 | + MAJOR(sb->s_dev), MINOR(sb->s_dev));
569 | + goto bypass_orig_flow;
570 | +orig_flow:
571 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
572 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
573 | seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
574 | MAJOR(sb->s_dev), MINOR(sb->s_dev));
575 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
576 | +bypass_orig_flow:
577 | +#endif
578 | +
579 | if (sb->s_op->show_path) {
580 | err = sb->s_op->show_path(m, mnt->mnt_root);
581 | if (err)
582 | @@ -202,6 +235,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
583 | struct super_block *sb = mnt_path.dentry->d_sb;
584 | int err;
585 |
586 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
587 | + if (susfs_sus_mount(mnt, &p->root))
588 | + return 0;
589 | +#endif
590 | +
591 | /* device */
592 | if (sb->s_op->show_devname) {
593 | seq_puts(m, "device ");
594 | @@ -285,6 +323,12 @@ static int mounts_open_common(struct inode *inode, struct file *file,
595 | p->show = show;
596 | p->cached_event = ~0ULL;
597 |
598 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
599 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
600 | + susfs_add_mnt_id_recorder(p->ns);
601 | + }
602 | +#endif
603 | +
604 | return 0;
605 |
606 | err_put_path:
607 | @@ -299,6 +343,13 @@ static int mounts_release(struct inode *inode, struct file *file)
608 | {
609 | struct seq_file *m = file->private_data;
610 | struct proc_mounts *p = m->private;
611 | +
612 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
613 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
614 | + susfs_remove_mnt_id_recorder();
615 | + }
616 | +#endif
617 | +
618 | path_put(&p->root);
619 | put_mnt_ns(p->ns);
620 | return seq_release_private(inode, file);
621 | diff --git a/fs/readdir.c b/fs/readdir.c
622 | index 3c5ce8a0ddc9..713f39dd48c1 100644
623 | --- a/fs/readdir.c
624 | +++ b/fs/readdir.c
625 | @@ -23,6 +23,10 @@
626 |
627 | #include
628 |
629 | +#ifdef CONFIG_KSU_SUSFS
630 | +#include
631 | +#endif
632 | +
633 | int iterate_dir(struct file *file, struct dir_context *ctx)
634 | {
635 | struct inode *inode = file_inode(file);
636 | @@ -309,6 +313,11 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
637 | if (dirent) {
638 | if (signal_pending(current))
639 | return -EINTR;
640 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
641 | + if (susfs_sus_ino_for_filldir64(ino)) {
642 | + return 0;
643 | + }
644 | +#endif
645 | if (__put_user(offset, &dirent->d_off))
646 | goto efault;
647 | }
648 | diff --git a/fs/stat.c b/fs/stat.c
649 | index be7d75d25c96..aefd1d138376 100644
650 | --- a/fs/stat.c
651 | +++ b/fs/stat.c
652 | @@ -21,6 +21,10 @@
653 | #include
654 | #include
655 |
656 | +#ifdef CONFIG_KSU_SUSFS
657 | +#include
658 | +#endif
659 | +
660 | /**
661 | * generic_fillattr - Fill in the basic attributes from the inode struct
662 | * @inode: Inode to use as the source
663 | @@ -110,6 +114,12 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
664 | {
665 | int retval;
666 |
667 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
668 | + if (susfs_sus_path_by_path(path, &retval, SYSCALL_FAMILY_ALL_ENOENT)) {
669 | + return retval;
670 | + }
671 | +#endif
672 | +
673 | retval = security_inode_getattr(path);
674 | if (retval)
675 | return retval;
676 | @@ -334,6 +344,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
677 | #endif
678 | tmp.st_blocks = stat->blocks;
679 | tmp.st_blksize = stat->blksize;
680 | +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
681 | + susfs_sus_kstat(tmp.st_ino, &tmp);
682 | +#endif
683 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
684 | }
685 |
686 | diff --git a/kernel/sys.c b/kernel/sys.c
687 | index 6ca0650c8f86..bca00627435c 100644
688 | --- a/kernel/sys.c
689 | +++ b/kernel/sys.c
690 | @@ -79,6 +79,10 @@
691 |
692 | #include "uid16.h"
693 |
694 | +#ifdef CONFIG_KSU_SUSFS
695 | +#include
696 | +#endif
697 | +
698 | #ifndef SET_UNALIGN_CTL
699 | # define SET_UNALIGN_CTL(a, b) (-EINVAL)
700 | #endif
701 | @@ -1261,6 +1265,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
702 | down_read(&uts_sem);
703 | memcpy(&tmp, utsname(), sizeof(tmp));
704 | up_read(&uts_sem);
705 | +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
706 | + susfs_spoof_uname(&tmp);
707 | +#endif
708 | if (copy_to_user(name, &tmp, sizeof(tmp)))
709 | return -EFAULT;
710 |
711 | diff --git a/mm/memfd.c b/mm/memfd.c
712 | index af394978646a..3887782b6d0c 100644
713 | --- a/mm/memfd.c
714 | +++ b/mm/memfd.c
715 | @@ -20,6 +20,10 @@
716 | #include
717 | #include
718 |
719 | +#ifdef CONFIG_KSU_SUSFS
720 | +#include
721 | +#endif
722 | +
723 | /*
724 | * We need a tag: a new tag would expand every radix_tree_node by 8 bytes,
725 | * so reuse a tag which we firmly believe is never set or cleared on tmpfs
726 | @@ -323,6 +327,13 @@ SYSCALL_DEFINE2(memfd_create,
727 | goto err_name;
728 | }
729 |
730 | +#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
731 | + if (susfs_sus_memfd(name)) {
732 | + error = -EFAULT;
733 | + goto err_name;
734 | + }
735 | +#endif
736 | +
737 | fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0);
738 | if (fd < 0) {
739 | error = fd;
740 |
--------------------------------------------------------------------------------
/kernel_patches/50_add_susfs_in_kernel-4.9.patch:
--------------------------------------------------------------------------------
1 | diff --git a/fs/Makefile b/fs/Makefile
2 | index 0e97f4b85bee..5ef37c17ee91 100644
3 | --- a/fs/Makefile
4 | +++ b/fs/Makefile
5 | @@ -13,6 +13,8 @@ obj-y := open.o read_write.o file_table.o super.o \
6 | pnode.o splice.o sync.o utimes.o \
7 | stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
8 |
9 | +obj-$(CONFIG_KSU_SUSFS) += susfs.o
10 | +
11 | ifeq ($(CONFIG_BLOCK),y)
12 | obj-y += buffer.o block_dev.o direct-io.o mpage.o
13 | else
14 | diff --git a/fs/internal.h b/fs/internal.h
15 | index 3e58863de514..4fe0133cc4f6 100644
16 | --- a/fs/internal.h
17 | +++ b/fs/internal.h
18 | @@ -74,6 +74,10 @@ extern int __mnt_want_write_file(struct file *);
19 | extern void __mnt_drop_write(struct vfsmount *);
20 | extern void __mnt_drop_write_file(struct file *);
21 |
22 | +#ifdef CONFIG_KSU_SUSFS
23 | +int path_umount(struct path *path, int flags);
24 | +#endif
25 | +
26 | /*
27 | * fs_struct.c
28 | */
29 | diff --git a/fs/namei.c b/fs/namei.c
30 | index 0cbf8f5a92f4..2ff97f64a110 100644
31 | --- a/fs/namei.c
32 | +++ b/fs/namei.c
33 | @@ -42,6 +42,10 @@
34 | #include "internal.h"
35 | #include "mount.h"
36 |
37 | +#ifdef CONFIG_KSU_SUSFS
38 | +#include
39 | +#endif
40 | +
41 | /* [Feb-1997 T. Schoebel-Theuer]
42 | * Fundamental changes in the pathname lookup mechanisms (namei)
43 | * were necessary because of omirr. The reason is that omirr needs
44 | @@ -3619,6 +3623,13 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
45 | int flags = op->lookup_flags;
46 | struct file *filp;
47 |
48 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
49 | + int error;
50 | + if (susfs_sus_path_by_filename(pathname, &error, SYSCALL_FAMILY_ALL_ENOENT)) {
51 | + return ERR_PTR(error);
52 | + }
53 | +#endif
54 | +
55 | set_nameidata(&nd, dfd, pathname);
56 | filp = path_openat(&nd, op, flags | LOOKUP_RCU);
57 | if (unlikely(filp == ERR_PTR(-ECHILD)))
58 | @@ -3819,6 +3830,19 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
59 | int error;
60 | unsigned int lookup_flags = 0;
61 |
62 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
63 | + struct filename* fname;
64 | + int status;
65 | +
66 | + fname = getname_safe(filename);
67 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKNOD);
68 | + putname_safe(fname);
69 | +
70 | + if (status) {
71 | + return error;
72 | + }
73 | +#endif
74 | +
75 | error = may_mknod(mode);
76 | if (error)
77 | return error;
78 | @@ -3899,6 +3923,19 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
79 | int error;
80 | unsigned int lookup_flags = LOOKUP_DIRECTORY;
81 |
82 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
83 | + struct filename* fname;
84 | + int status;
85 | +
86 | + fname = getname_safe(pathname);
87 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKDIRAT);
88 | + putname_safe(fname);
89 | +
90 | + if (status) {
91 | + return error;
92 | + }
93 | +#endif
94 | +
95 | retry:
96 | dentry = user_path_create(dfd, pathname, &path, lookup_flags);
97 | if (IS_ERR(dentry))
98 | @@ -3976,6 +4013,21 @@ static long do_rmdir(int dfd, const char __user *pathname)
99 | struct qstr last;
100 | int type;
101 | unsigned int lookup_flags = 0;
102 | +
103 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
104 | + struct filename* fname;
105 | + int status;
106 | +
107 | + fname = getname_safe(pathname);
108 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RMDIR);
109 | + putname_safe(fname);
110 | +
111 | + if (status) {
112 | + return error;
113 | + }
114 | + error = 0;
115 | +#endif
116 | +
117 | retry:
118 | name = user_path_parent(dfd, pathname,
119 | &path, &last, &type, lookup_flags);
120 | @@ -4112,6 +4164,20 @@ static long do_unlinkat(int dfd, const char __user *pathname)
121 | struct inode *inode = NULL;
122 | struct inode *delegated_inode = NULL;
123 | unsigned int lookup_flags = 0;
124 | +
125 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
126 | + struct filename* fname;
127 | + int status;
128 | +
129 | + fname = getname_safe(pathname);
130 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_UNLINKAT);
131 | + putname_safe(fname);
132 | +
133 | + if (status) {
134 | + return error;
135 | + }
136 | +#endif
137 | +
138 | retry:
139 | name = user_path_parent(dfd, pathname,
140 | &path, &last, &type, lookup_flags);
141 | @@ -4226,6 +4292,19 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
142 | struct path path;
143 | unsigned int lookup_flags = 0;
144 |
145 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
146 | + struct filename* fname;
147 | + int status;
148 | +
149 | + fname = getname_safe(newname);
150 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_SYMLINKAT_NEWNAME);
151 | + putname_safe(fname);
152 | +
153 | + if (status) {
154 | + return error;
155 | + }
156 | +#endif
157 | +
158 | from = getname(oldname);
159 | if (IS_ERR(from))
160 | return PTR_ERR(from);
161 | @@ -4357,6 +4436,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
162 | int how = 0;
163 | int error;
164 |
165 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
166 | + struct filename* fname;
167 | + int status;
168 | +
169 | + fname = getname_safe(oldname);
170 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_OLDNAME);
171 | + putname_safe(fname);
172 | +
173 | + if (status) {
174 | + return error;
175 | + }
176 | +
177 | + fname = getname_safe(newname);
178 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_NEWNAME);
179 | + putname_safe(fname);
180 | +
181 | + if (status) {
182 | + return error;
183 | + }
184 | +#endif
185 | +
186 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
187 | return -EINVAL;
188 | /*
189 | @@ -4620,6 +4720,27 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
190 | bool should_retry = false;
191 | int error;
192 |
193 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
194 | + struct filename* fname;
195 | + int status;
196 | +
197 | + fname = getname_safe(oldname);
198 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_OLDNAME);
199 | + putname_safe(fname);
200 | +
201 | + if (status) {
202 | + return error;
203 | + }
204 | +
205 | + fname = getname_safe(newname);
206 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_NEWNAME);
207 | + putname_safe(fname);
208 | +
209 | + if (status) {
210 | + return error;
211 | + }
212 | +#endif
213 | +
214 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
215 | return -EINVAL;
216 |
217 | diff --git a/fs/open.c b/fs/open.c
218 | index f2b82c462fbb..8c73e9371764 100644
219 | --- a/fs/open.c
220 | +++ b/fs/open.c
221 | @@ -34,6 +34,10 @@
222 |
223 | #include "internal.h"
224 |
225 | +#ifdef CONFIG_KSU_SUSFS
226 | +#include
227 | +#endif
228 | +
229 | int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
230 | unsigned int time_attrs, struct file *filp)
231 | {
232 | @@ -140,6 +144,18 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
233 | unsigned int lookup_flags = LOOKUP_FOLLOW;
234 | struct path path;
235 | int error;
236 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
237 | + struct filename* fname;
238 | + int status;
239 | +
240 | + fname = getname_safe(pathname);
241 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
242 | + putname_safe(fname);
243 | +
244 | + if (status) {
245 | + return error;
246 | + }
247 | +#endif
248 |
249 | if (length < 0) /* sorry, but loff_t says... */
250 | return -EINVAL;
251 | @@ -373,10 +373,27 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
252 | struct vfsmount *mnt;
253 | int res;
254 | unsigned int lookup_flags = LOOKUP_FOLLOW;
255 | +
256 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
257 | + struct filename* fname;
258 | + int status;
259 | + int error;
260 | +#endif
261 | +
262 | #ifdef CONFIG_KSU
263 | ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
264 | #endif
265 |
266 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
267 | + fname = getname_safe(filename);
268 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
269 | + putname_safe(fname);
270 | +
271 | + if (status) {
272 | + return error;
273 | + }
274 | +#endif
275 | +
276 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
277 | return -EINVAL;
278 |
279 | @@ -467,6 +497,20 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename)
280 | struct path path;
281 | int error;
282 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
283 | +
284 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
285 | + struct filename* fname;
286 | + int status;
287 | +
288 | + fname = getname_safe(filename);
289 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
290 | + putname_safe(fname);
291 | +
292 | + if (status) {
293 | + return error;
294 | + }
295 | +#endif
296 | +
297 | retry:
298 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
299 | if (error)
300 | diff --git a/fs/proc/base.c b/fs/proc/base.c
301 | index b6959f6dae5b..9665ef85f778 100644
302 | --- a/fs/proc/base.c
303 | +++ b/fs/proc/base.c
304 | @@ -97,6 +97,10 @@
305 |
306 | #include "../../lib/kstrtox.h"
307 |
308 | +#ifdef CONFIG_KSU_SUSFS
309 | +#include
310 | +#endif
311 | +
312 | /* NOTE:
313 | * Implementing inode permission operations in /proc is almost
314 | * certainly an error. Permission checks need to happen during
315 | @@ -1828,6 +1832,15 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
316 | char *pathname;
317 | int len;
318 |
319 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
320 | + struct mm_struct *mm;
321 | + struct vm_area_struct *vma;
322 | + struct file *vma_file;
323 | + struct dentry *vma_dentry;
324 | + struct inode *vma_inode;
325 | + unsigned long ino;
326 | +#endif
327 | +
328 | if (!tmp)
329 | return -ENOMEM;
330 |
331 | @@ -1839,6 +1852,38 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
332 |
333 | if (len > buflen)
334 | len = buflen;
335 | +
336 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
337 | + if (!susfs_is_sus_proc_fd_link_list_empty()) {
338 | + if (susfs_sus_proc_fd_link(pathname, len))
339 | + goto orig_flow;
340 | + }
341 | +#endif
342 | +
343 | +
344 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
345 | + if (!susfs_is_sus_maps_list_empty()) {
346 | + mm = current->mm;
347 | + down_read(&mm->mmap_sem);
348 | + for (vma = mm->mmap; vma; vma = vma->vm_next) {
349 | + if (vma->vm_file) {
350 | + vma_file = vma->vm_file;
351 | + vma_dentry = vma_file->f_path.dentry;
352 | + if (vma_dentry == path->dentry) {
353 | + vma_inode = file_inode(vma_file);
354 | + ino = vma_inode->i_ino;
355 | + susfs_sus_map_files_readlink(ino, pathname);
356 | + break;
357 | + }
358 | + }
359 | + }
360 | + up_read(&mm->mmap_sem);
361 | + }
362 | +#endif
363 | +
364 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
365 | +orig_flow:
366 | +#endif
367 | if (copy_to_user(buffer, pathname, len))
368 | len = -EFAULT;
369 | out:
370 | @@ -2207,6 +2252,9 @@ struct map_files_info {
371 | fmode_t mode;
372 | unsigned long len;
373 | unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
374 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
375 | + int susfs_action;
376 | +#endif
377 | };
378 |
379 | /*
380 | @@ -2269,6 +2317,10 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
381 | int result;
382 | struct mm_struct *mm;
383 |
384 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
385 | + int ret = 0;
386 | +#endif
387 | +
388 | result = -ENOENT;
389 | task = get_proc_task(dir);
390 | if (!task)
391 | @@ -2291,6 +2343,23 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
392 | if (!vma)
393 | goto out_no_vma;
394 |
395 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
396 | + if (vma->vm_file) {
397 | + ret = susfs_sus_map_files_instantiate(vma);
398 | + if (ret == 1) {
399 | + if (vma->vm_file->f_mode & FMODE_WRITE) {
400 | + vma->vm_file->f_mode &= ~FMODE_WRITE;
401 | + }
402 | + goto orig_flow;
403 | + }
404 | + if (ret == 2) {
405 | + result = -ENOENT;
406 | + goto out_no_vma;
407 | + }
408 | + }
409 | +orig_flow:
410 | +#endif
411 | +
412 | if (vma->vm_file)
413 | result = proc_map_files_instantiate(dir, dentry, task,
414 | (void *)(unsigned long)vma->vm_file->f_mode);
415 | @@ -2322,6 +2391,10 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
416 | struct map_files_info *p;
417 | int ret;
418 |
419 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
420 | + int susfs_ret = 0;
421 | +#endif
422 | +
423 | ret = -ENOENT;
424 | task = get_proc_task(file_inode(file));
425 | if (!task)
426 | @@ -2380,6 +2453,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
427 | info.len = snprintf(info.name,
428 | sizeof(info.name), "%lx-%lx",
429 | vma->vm_start, vma->vm_end);
430 | +
431 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
432 | + susfs_ret = susfs_sus_map_files_instantiate(vma);
433 | + info.susfs_action = susfs_ret;
434 | +#endif
435 | +
436 | if (flex_array_put(fa, i++, &info, GFP_KERNEL))
437 | BUG();
438 | }
439 | @@ -2388,12 +2467,28 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
440 |
441 | for (i = 0; i < nr_files; i++) {
442 | p = flex_array_get(fa, i);
443 | +
444 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
445 | + if (p->susfs_action == SUSFS_MAP_FILES_ACTION_REMOVE_WRITE_PERM) {
446 | + if (p->mode & FMODE_WRITE) {
447 | + p->mode &= ~FMODE_WRITE;
448 | + }
449 | + } else if (p->susfs_action == SUSFS_MAP_FILES_ACTION_HIDE_DENTRY) {
450 | + goto skip_proc_fill_cache;
451 | + }
452 | +#endif
453 | +
454 | if (!proc_fill_cache(file, ctx,
455 | p->name, p->len,
456 | proc_map_files_instantiate,
457 | task,
458 | (void *)(unsigned long)p->mode))
459 | break;
460 | +
461 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
462 | +skip_proc_fill_cache:
463 | +#endif
464 | +
465 | ctx->pos++;
466 | }
467 | if (fa)
468 | diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
469 | index f4a77817ad74..c2b36c3b317a 100644
470 | --- a/fs/proc/task_mmu.c
471 | +++ b/fs/proc/task_mmu.c
472 | @@ -22,6 +22,10 @@
473 | #include
474 | #include "internal.h"
475 |
476 | +#ifdef CONFIG_KSU_SUSFS
477 | +#include
478 | +#endif
479 | +
480 | void task_mem(struct seq_file *m, struct mm_struct *mm)
481 | {
482 | unsigned long text, lib, swap, ptes, pmds, anon, file, shmem;
483 | @@ -358,6 +362,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
484 | unsigned long start, end;
485 | dev_t dev = 0;
486 | const char *name = NULL;
487 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
488 | + char *out_name;
489 | + int ret = 0;
490 | +#endif
491 |
492 | if (file) {
493 | struct inode *inode = file_inode(vma->vm_file);
494 | @@ -369,8 +377,28 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
495 | /* We don't show the stack guard page in /proc/maps */
496 | start = vma->vm_start;
497 | end = vma->vm_end;
498 | +
499 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
500 | + out_name = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
501 | + if (!out_name)
502 | + goto orig_flow;
503 | + ret = susfs_sus_maps(ino, end - start, &ino, &dev, &flags, &pgoff, vma, out_name);
504 | +
505 | +orig_flow:
506 | +#endif
507 | +
508 | show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);
509 |
510 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
511 | + if (ret == 2) {
512 | + seq_pad(m, ' ');
513 | + seq_puts(m, out_name);
514 | + seq_putc(m, '\n');
515 | + kfree(out_name);
516 | + return;
517 | + }
518 | + kfree(out_name);
519 | +#endif
520 | /*
521 | * Print the dentry name for named mappings, and a
522 | * special [heap] marker for the heap:
523 | diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
524 | index 6863773aff25..493de1b4e7de 100644
525 | --- a/fs/proc_namespace.c
526 | +++ b/fs/proc_namespace.c
527 | @@ -15,6 +15,10 @@
528 | #include "pnode.h"
529 | #include "internal.h"
530 |
531 | +#ifdef CONFIG_KSU_SUSFS
532 | +#include
533 | +#endif
534 | +
535 | static unsigned mounts_poll(struct file *file, poll_table *wait)
536 | {
537 | struct seq_file *m = file->private_data;
538 | @@ -99,6 +103,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
539 | struct super_block *sb = mnt_path.dentry->d_sb;
540 | int err;
541 |
542 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
543 | + if (susfs_sus_mount(mnt, &p->root))
544 | + return SEQ_SKIP;
545 | +#endif
546 | +
547 | if (sb->s_op->show_devname) {
548 | err = sb->s_op->show_devname(m, mnt_path.dentry);
549 | if (err)
550 | @@ -135,8 +144,30 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
551 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
552 | int err;
553 |
554 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
555 | + int out_mnt_id = 0, out_parent_mnt_id = 0;
556 | + int status = 1;
557 | +#endif
558 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
559 | + if (susfs_sus_mount(mnt, &p->root))
560 | + return 0;
561 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
562 | + if (!uid_matches_proc_need_to_reorder_mnt_id())
563 | + goto orig_flow;
564 | + status = susfs_get_fake_mnt_id(r->mnt_id, &out_mnt_id, &out_parent_mnt_id);
565 | + if (status)
566 | + goto orig_flow;
567 | + seq_printf(m, "%i %i %u:%u ", out_mnt_id, out_parent_mnt_id,
568 | + MAJOR(sb->s_dev), MINOR(sb->s_dev));
569 | + goto bypass_orig_flow;
570 | +orig_flow:
571 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
572 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
573 | seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
574 | MAJOR(sb->s_dev), MINOR(sb->s_dev));
575 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
576 | +bypass_orig_flow:
577 | +#endif
578 | if (sb->s_op->show_path) {
579 | err = sb->s_op->show_path(m, mnt->mnt_root);
580 | if (err)
581 | @@ -199,6 +230,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
582 | struct super_block *sb = mnt_path.dentry->d_sb;
583 | int err;
584 |
585 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
586 | + if (susfs_sus_mount(mnt, &p->root))
587 | + return 0;
588 | +#endif
589 | +
590 | /* device */
591 | if (sb->s_op->show_devname) {
592 | seq_puts(m, "device ");
593 | @@ -282,6 +318,12 @@ static int mounts_open_common(struct inode *inode, struct file *file,
594 | p->show = show;
595 | p->cached_event = ~0ULL;
596 |
597 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
598 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
599 | + susfs_add_mnt_id_recorder(p->ns);
600 | + }
601 | +#endif
602 | +
603 | return 0;
604 |
605 | err_put_path:
606 | @@ -296,6 +338,13 @@ static int mounts_release(struct inode *inode, struct file *file)
607 | {
608 | struct seq_file *m = file->private_data;
609 | struct proc_mounts *p = m->private;
610 | +
611 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
612 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
613 | + susfs_remove_mnt_id_recorder();
614 | + }
615 | +#endif
616 | +
617 | path_put(&p->root);
618 | put_mnt_ns(p->ns);
619 | return seq_release_private(inode, file);
620 | diff --git a/fs/readdir.c b/fs/readdir.c
621 | index 1059f2a9be0b..41e5677c178d 100644
622 | --- a/fs/readdir.c
623 | +++ b/fs/readdir.c
624 | @@ -21,6 +21,10 @@
625 |
626 | #include
627 |
628 | +#ifdef CONFIG_KSU_SUSFS
629 | +#include
630 | +#endif
631 | +
632 | int iterate_dir(struct file *file, struct dir_context *ctx)
633 | {
634 | struct inode *inode = file_inode(file);
635 | @@ -305,6 +309,11 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
636 | if (dirent) {
637 | if (signal_pending(current))
638 | return -EINTR;
639 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
640 | + if (susfs_sus_ino_for_filldir64(ino)) {
641 | + return 0;
642 | + }
643 | +#endif
644 | if (__put_user(offset, &dirent->d_off))
645 | goto efault;
646 | }
647 | diff --git a/fs/stat.c b/fs/stat.c
648 | index 068fdbcc9e26..ffb058f2b58f 100644
649 | --- a/fs/stat.c
650 | +++ b/fs/stat.c
651 | @@ -18,6 +18,10 @@
652 | #include
653 | #include
654 |
655 | +#ifdef CONFIG_KSU_SUSFS
656 | +#include
657 | +#endif
658 | +
659 | void generic_fillattr(struct inode *inode, struct kstat *stat)
660 | {
661 | stat->dev = inode->i_sb->s_dev;
662 | @@ -66,6 +70,12 @@ int vfs_getattr(struct path *path, struct kstat *stat)
663 | {
664 | int retval;
665 |
666 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
667 | + if (susfs_sus_path_by_path(path, &retval, SYSCALL_FAMILY_ALL_ENOENT)) {
668 | + return retval;
669 | + }
670 | +#endif
671 | +
672 | retval = security_inode_getattr(path);
673 | if (retval)
674 | return retval;
675 | @@ -260,6 +270,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
676 | #endif
677 | tmp.st_blocks = stat->blocks;
678 | tmp.st_blksize = stat->blksize;
679 | +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
680 | + susfs_sus_kstat(tmp.st_ino, &tmp);
681 | +#endif
682 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
683 | }
684 |
685 | diff --git a/kernel/sys.c b/kernel/sys.c
686 | index a7f823224546..893b17bf71c6 100644
687 | --- a/kernel/sys.c
688 | +++ b/kernel/sys.c
689 | @@ -66,6 +66,10 @@
690 | #include
691 | #include
692 |
693 | +#ifdef CONFIG_KSU_SUSFS
694 | +#include
695 | +#endif
696 | +
697 | #ifndef SET_UNALIGN_CTL
698 | # define SET_UNALIGN_CTL(a, b) (-EINVAL)
699 | #endif
700 | @@ -1150,6 +1154,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
701 | down_read(&uts_sem);
702 | memcpy(&tmp, utsname(), sizeof(tmp));
703 | up_read(&uts_sem);
704 | +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
705 | + susfs_spoof_uname(&tmp);
706 | +#endif
707 | if (copy_to_user(name, &tmp, sizeof(tmp)))
708 | return -EFAULT;
709 |
710 | diff --git a/mm/shmem.c b/mm/shmem.c
711 | index 9cb863a19d07..f91b4b4595ca 100644
712 | --- a/mm/shmem.c
713 | +++ b/mm/shmem.c
714 | @@ -33,6 +33,9 @@
715 | #include
716 | #include
717 | #include
718 | +#ifdef CONFIG_KSU_SUSFS
719 | +#include
720 | +#endif
721 |
722 | static struct vfsmount *shm_mnt;
723 |
724 | @@ -3562,6 +3565,13 @@ SYSCALL_DEFINE2(memfd_create,
725 | goto err_name;
726 | }
727 |
728 | +#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
729 | + if (susfs_sus_memfd(name)) {
730 | + error = -EFAULT;
731 | + goto err_name;
732 | + }
733 | +#endif
734 | +
735 | fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0);
736 | if (fd < 0) {
737 | error = fd;
738 |
--------------------------------------------------------------------------------
/kernel_patches/50_add_susfs_in_kernel-5.4.patch:
--------------------------------------------------------------------------------
1 | diff --git a/fs/Makefile b/fs/Makefile
2 | index 1c949ac25dbb..aff1cd7061e7 100644
3 | --- a/fs/Makefile
4 | +++ b/fs/Makefile
5 | @@ -14,8 +14,11 @@ obj-y := open.o read_write.o file_table.o super.o \
6 | attr.o bad_inode.o file.o filesystems.o namespace.o \
7 | seq_file.o xattr.o libfs.o fs-writeback.o \
8 | pnode.o splice.o sync.o utimes.o d_path.o \
9 | - stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
10 | - fs_types.o fs_context.o fs_parser.o fsopen.o
11 | + stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
12 | +
13 | +obj-$(CONFIG_KSU_SUSFS) += susfs.o
14 | +
15 | +obj-y += fs_types.o fs_context.o fs_parser.o fsopen.o
16 |
17 | ifeq ($(CONFIG_BLOCK),y)
18 | obj-y += buffer.o block_dev.o direct-io.o mpage.o
19 | diff --git a/fs/internal.h b/fs/internal.h
20 | index d1201cdcc9fc..ffd909a640b9 100644
21 | --- a/fs/internal.h
22 | +++ b/fs/internal.h
23 | @@ -89,6 +89,11 @@ extern int __mnt_want_write_file(struct file *);
24 | extern void __mnt_drop_write_file(struct file *);
25 |
26 | extern void dissolve_on_fput(struct vfsmount *);
27 | +
28 | +#ifdef CONFIG_KSU_SUSFS
29 | +int path_umount(struct path *path, int flags);
30 | +#endif
31 | +
32 | /*
33 | * fs_struct.c
34 | */
35 | diff --git a/fs/namei.c b/fs/namei.c
36 | index ed6261cd4577..a660018904c9 100644
37 | --- a/fs/namei.c
38 | +++ b/fs/namei.c
39 | @@ -46,6 +46,10 @@
40 | #define CREATE_TRACE_POINTS
41 | #include
42 |
43 | +#ifdef CONFIG_KSU_SUSFS
44 | +#include
45 | +#endif
46 | +
47 | /* [Feb-1997 T. Schoebel-Theuer]
48 | * Fundamental changes in the pathname lookup mechanisms (namei)
49 | * were necessary because of omirr. The reason is that omirr needs
50 | @@ -3520,6 +3524,13 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
51 | int flags = op->lookup_flags;
52 | struct file *filp;
53 |
54 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
55 | + int error;
56 | + if (susfs_sus_path_by_filename(pathname, &error, SYSCALL_FAMILY_ALL_ENOENT)) {
57 | + return ERR_PTR(error);
58 | + }
59 | +#endif
60 | +
61 | set_nameidata(&nd, dfd, pathname);
62 | filp = path_openat(&nd, op, flags | LOOKUP_RCU);
63 | if (unlikely(filp == ERR_PTR(-ECHILD)))
64 | @@ -3707,6 +3718,19 @@ long do_mknodat(int dfd, const char __user *filename, umode_t mode,
65 | int error;
66 | unsigned int lookup_flags = 0;
67 |
68 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
69 | + struct filename* fname;
70 | + int status;
71 | +
72 | + fname = getname_safe(filename);
73 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKNOD);
74 | + putname_safe(fname);
75 | +
76 | + if (status) {
77 | + return error;
78 | + }
79 | +#endif
80 | +
81 | error = may_mknod(mode);
82 | if (error)
83 | return error;
84 | @@ -3787,6 +3811,19 @@ long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
85 | int error;
86 | unsigned int lookup_flags = LOOKUP_DIRECTORY;
87 |
88 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
89 | + struct filename* fname;
90 | + int status;
91 | +
92 | + fname = getname_safe(pathname);
93 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_MKDIRAT);
94 | + putname_safe(fname);
95 | +
96 | + if (status) {
97 | + return error;
98 | + }
99 | +#endif
100 | +
101 | retry:
102 | dentry = user_path_create(dfd, pathname, &path, lookup_flags);
103 | if (IS_ERR(dentry))
104 | @@ -3863,6 +3900,21 @@ long do_rmdir(int dfd, const char __user *pathname)
105 | struct qstr last;
106 | int type;
107 | unsigned int lookup_flags = 0;
108 | +
109 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
110 | + struct filename* fname;
111 | + int status;
112 | +
113 | + fname = getname_safe(pathname);
114 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RMDIR);
115 | + putname_safe(fname);
116 | +
117 | + if (status) {
118 | + return error;
119 | + }
120 | + error = 0;
121 | +#endif
122 | +
123 | retry:
124 | name = filename_parentat(dfd, getname(pathname), lookup_flags,
125 | &path, &last, &type);
126 | @@ -3994,6 +4046,17 @@ long do_unlinkat(int dfd, struct filename *name)
127 | struct inode *inode = NULL;
128 | struct inode *delegated_inode = NULL;
129 | unsigned int lookup_flags = 0;
130 | +
131 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
132 | + int status;
133 | +
134 | + status = susfs_sus_path_by_filename(name, &error, SYSCALL_FAMILY_UNLINKAT);
135 | +
136 | + if (status) {
137 | + return error;
138 | + }
139 | +#endif
140 | +
141 | retry:
142 | name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type);
143 | if (IS_ERR(name))
144 | @@ -4101,6 +4164,19 @@ long do_symlinkat(const char __user *oldname, int newdfd,
145 | struct path path;
146 | unsigned int lookup_flags = 0;
147 |
148 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
149 | + struct filename* fname;
150 | + int status;
151 | +
152 | + fname = getname_safe(newname);
153 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_SYMLINKAT_NEWNAME);
154 | + putname_safe(fname);
155 | +
156 | + if (status) {
157 | + return error;
158 | + }
159 | +#endif
160 | +
161 | from = getname(oldname);
162 | if (IS_ERR(from))
163 | return PTR_ERR(from);
164 | @@ -4232,6 +4308,27 @@ int do_linkat(int olddfd, const char __user *oldname, int newdfd,
165 | int how = 0;
166 | int error;
167 |
168 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
169 | + struct filename* fname;
170 | + int status;
171 | +
172 | + fname = getname_safe(oldname);
173 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_OLDNAME);
174 | + putname_safe(fname);
175 | +
176 | + if (status) {
177 | + return error;
178 | + }
179 | +
180 | + fname = getname_safe(newname);
181 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_LINKAT_NEWNAME);
182 | + putname_safe(fname);
183 | +
184 | + if (status) {
185 | + return error;
186 | + }
187 | +#endif
188 | +
189 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
190 | return -EINVAL;
191 | /*
192 | @@ -4494,6 +4591,27 @@ static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
193 | bool should_retry = false;
194 | int error;
195 |
196 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
197 | + struct filename* fname;
198 | + int status;
199 | +
200 | + fname = getname_safe(oldname);
201 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_OLDNAME);
202 | + putname_safe(fname);
203 | +
204 | + if (status) {
205 | + return error;
206 | + }
207 | +
208 | + fname = getname_safe(newname);
209 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_RENAMEAT2_NEWNAME);
210 | + putname_safe(fname);
211 | +
212 | + if (status) {
213 | + return error;
214 | + }
215 | +#endif
216 | +
217 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
218 | return -EINVAL;
219 |
220 | diff --git a/fs/open.c b/fs/open.c
221 | index 88e42c2e8742..6eea57aa0cee 100644
222 | --- a/fs/open.c
223 | +++ b/fs/open.c
224 | @@ -35,6 +35,10 @@
225 |
226 | #include "internal.h"
227 |
228 | +#ifdef CONFIG_KSU_SUSFS
229 | +#include
230 | +#endif
231 | +
232 | int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
233 | struct file *filp)
234 | {
235 | @@ -123,6 +127,18 @@ long do_sys_truncate(const char __user *pathname, loff_t length)
236 | unsigned int lookup_flags = LOOKUP_FOLLOW;
237 | struct path path;
238 | int error;
239 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
240 | + struct filename* fname;
241 | + int status;
242 | +
243 | + fname = getname_safe(pathname);
244 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
245 | + putname_safe(fname);
246 | +
247 | + if (status) {
248 | + return error;
249 | + }
250 | +#endif
251 |
252 | if (length < 0) /* sorry, but loff_t says... */
253 | return -EINVAL;
254 | @@ -354,6 +370,22 @@ long do_faccessat(int dfd, const char __user *filename, int mode)
255 | int res;
256 | unsigned int lookup_flags = LOOKUP_FOLLOW;
257 |
258 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
259 | + struct filename* fname;
260 | + int status;
261 | + int error;
262 | +#endif
263 | +
264 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
265 | + fname = getname_safe(filename);
266 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
267 | + putname_safe(fname);
268 | +
269 | + if (status) {
270 | + return error;
271 | + }
272 | +#endif
273 | +
274 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
275 | return -EINVAL;
276 |
277 | @@ -455,6 +487,20 @@ int ksys_chdir(const char __user *filename)
278 | struct path path;
279 | int error;
280 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
281 | +
282 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
283 | + struct filename* fname;
284 | + int status;
285 | +
286 | + fname = getname_safe(filename);
287 | + status = susfs_sus_path_by_filename(fname, &error, SYSCALL_FAMILY_ALL_ENOENT);
288 | + putname_safe(fname);
289 | +
290 | + if (status) {
291 | + return error;
292 | + }
293 | +#endif
294 | +
295 | retry:
296 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
297 | if (error)
298 | diff --git a/fs/proc/base.c b/fs/proc/base.c
299 | index c72ee7d93d43..00184b10fbf3 100644
300 | --- a/fs/proc/base.c
301 | +++ b/fs/proc/base.c
302 | @@ -101,6 +101,10 @@
303 |
304 | #include "../../lib/kstrtox.h"
305 |
306 | +#ifdef CONFIG_KSU_SUSFS
307 | +#include
308 | +#endif
309 | +
310 | /* NOTE:
311 | * Implementing inode permission operations in /proc is almost
312 | * certainly an error. Permission checks need to happen during
313 | @@ -1733,6 +1737,15 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
314 | char *pathname;
315 | int len;
316 |
317 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
318 | + struct mm_struct *mm;
319 | + struct vm_area_struct *vma;
320 | + struct file *vma_file;
321 | + struct dentry *vma_dentry;
322 | + struct inode *vma_inode;
323 | + unsigned long ino;
324 | +#endif
325 | +
326 | if (!tmp)
327 | return -ENOMEM;
328 |
329 | @@ -1744,6 +1757,39 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
330 |
331 | if (len > buflen)
332 | len = buflen;
333 | +
334 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
335 | + if (!susfs_is_sus_proc_fd_link_list_empty()) {
336 | + if (susfs_sus_proc_fd_link(pathname, len))
337 | + goto orig_flow;
338 | + }
339 | +#endif
340 | +
341 | +
342 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
343 | + if (!susfs_is_sus_maps_list_empty()) {
344 | + mm = current->mm;
345 | + down_read(&mm->mmap_sem);
346 | + for (vma = mm->mmap; vma; vma = vma->vm_next) {
347 | + if (vma->vm_file) {
348 | + vma_file = vma->vm_file;
349 | + vma_dentry = vma_file->f_path.dentry;
350 | + if (vma_dentry == path->dentry) {
351 | + vma_inode = file_inode(vma_file);
352 | + ino = vma_inode->i_ino;
353 | + susfs_sus_map_files_readlink(ino, pathname);
354 | + break;
355 | + }
356 | + }
357 | + }
358 | + up_read(&mm->mmap_sem);
359 | + }
360 | +#endif
361 | +
362 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
363 | +orig_flow:
364 | +#endif
365 | +
366 | if (copy_to_user(buffer, pathname, len))
367 | len = -EFAULT;
368 | out:
369 | @@ -2148,6 +2194,9 @@ struct map_files_info {
370 | unsigned long start;
371 | unsigned long end;
372 | fmode_t mode;
373 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
374 | + int susfs_action;
375 | +#endif
376 | };
377 |
378 | /*
379 | @@ -2208,6 +2257,10 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
380 | struct dentry *result;
381 | struct mm_struct *mm;
382 |
383 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
384 | + int ret = 0;
385 | +#endif
386 | +
387 | result = ERR_PTR(-ENOENT);
388 | task = get_proc_task(dir);
389 | if (!task)
390 | @@ -2234,6 +2287,23 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
391 | if (!vma)
392 | goto out_no_vma;
393 |
394 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
395 | + if (vma->vm_file) {
396 | + ret = susfs_sus_map_files_instantiate(vma);
397 | + if (ret == 1) {
398 | + if (vma->vm_file->f_mode & FMODE_WRITE) {
399 | + vma->vm_file->f_mode &= ~FMODE_WRITE;
400 | + }
401 | + goto orig_flow;
402 | + }
403 | + if (ret == 2) {
404 | + result = ERR_PTR(-ENOENT);
405 | + goto out_no_vma;
406 | + }
407 | + }
408 | +orig_flow:
409 | +#endif
410 | +
411 | if (vma->vm_file)
412 | result = proc_map_files_instantiate(dentry, task,
413 | (void *)(unsigned long)vma->vm_file->f_mode);
414 | @@ -2265,6 +2335,10 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
415 | struct map_files_info *p;
416 | int ret;
417 |
418 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
419 | + int susfs_ret = 0;
420 | +#endif
421 | +
422 | genradix_init(&fa);
423 |
424 | ret = -ENOENT;
425 | @@ -2319,6 +2393,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
426 | p->start = vma->vm_start;
427 | p->end = vma->vm_end;
428 | p->mode = vma->vm_file->f_mode;
429 | +
430 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
431 | + struct map_files_info info;
432 | + susfs_ret = susfs_sus_map_files_instantiate(vma);
433 | + info.susfs_action = susfs_ret;
434 | +#endif
435 | }
436 | up_read(&mm->mmap_sem);
437 | mmput(mm);
438 | @@ -2329,12 +2409,28 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
439 |
440 | p = genradix_ptr(&fa, i);
441 | len = snprintf(buf, sizeof(buf), "%lx-%lx", p->start, p->end);
442 | +
443 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
444 | + if (p->susfs_action == SUSFS_MAP_FILES_ACTION_REMOVE_WRITE_PERM) {
445 | + if (p->mode & FMODE_WRITE) {
446 | + p->mode &= ~FMODE_WRITE;
447 | + }
448 | + } else if (p->susfs_action == SUSFS_MAP_FILES_ACTION_HIDE_DENTRY) {
449 | + goto skip_proc_fill_cache;
450 | + }
451 | +#endif
452 | +
453 | if (!proc_fill_cache(file, ctx,
454 | buf, len,
455 | proc_map_files_instantiate,
456 | task,
457 | (void *)(unsigned long)p->mode))
458 | break;
459 | +
460 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
461 | +skip_proc_fill_cache:
462 | +#endif
463 | +
464 | ctx->pos++;
465 | }
466 |
467 | diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
468 | index 4ba5e79f2d3d..2eb519ced9d4 100644
469 | --- a/fs/proc/task_mmu.c
470 | +++ b/fs/proc/task_mmu.c
471 | @@ -27,6 +27,10 @@
472 | #include
473 | #include "internal.h"
474 |
475 | +#ifdef CONFIG_KSU_SUSFS
476 | +#include
477 | +#endif
478 | +
479 | #define SEQ_PUT_DEC(str, val) \
480 | seq_put_decimal_ull_width(m, str, (val) << (PAGE_SHIFT-10), 8)
481 | void task_mem(struct seq_file *m, struct mm_struct *mm)
482 | @@ -502,6 +506,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
483 | unsigned long start, end;
484 | dev_t dev = 0;
485 | const char *name = NULL;
486 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
487 | + char *out_name;
488 | + int ret = 0;
489 | +#endif
490 |
491 | if (file) {
492 | struct inode *inode = file_inode(vma->vm_file);
493 | @@ -512,9 +520,29 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
494 |
495 | start = vma->vm_start;
496 | end = vma->vm_end;
497 | +
498 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
499 | + out_name = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
500 | + if (!out_name)
501 | + goto orig_flow;
502 | + ret = susfs_sus_maps(ino, end - start, &ino, &dev, &flags, &pgoff, vma, out_name);
503 | +
504 | +orig_flow:
505 | +#endif
506 | +
507 | if (show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino))
508 | return;
509 |
510 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
511 | + if (ret == 2) {
512 | + seq_pad(m, ' ');
513 | + seq_puts(m, out_name);
514 | + seq_putc(m, '\n');
515 | + kfree(out_name);
516 | + return;
517 | + }
518 | + kfree(out_name);
519 | +#endif
520 | /*
521 | * Print the dentry name for named mappings, and a
522 | * special [heap] marker for the heap:
523 | diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
524 | index 5b8d065fa83c..dc6ba954ba50 100644
525 | --- a/fs/proc_namespace.c
526 | +++ b/fs/proc_namespace.c
527 | @@ -18,6 +18,10 @@
528 | #include "pnode.h"
529 | #include "internal.h"
530 |
531 | +#ifdef CONFIG_KSU_SUSFS
532 | +#include
533 | +#endif
534 | +
535 | static __poll_t mounts_poll(struct file *file, poll_table *wait)
536 | {
537 | struct seq_file *m = file->private_data;
538 | @@ -102,6 +106,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
539 | struct super_block *sb = mnt_path.dentry->d_sb;
540 | int err;
541 |
542 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
543 | + if (susfs_sus_mount(mnt, &p->root))
544 | + return 0;
545 | +#endif
546 | +
547 | if (sb->s_op->show_devname) {
548 | err = sb->s_op->show_devname(m, mnt_path.dentry);
549 | if (err)
550 | @@ -138,8 +147,31 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
551 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
552 | int err;
553 |
554 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
555 | + int out_mnt_id = 0, out_parent_mnt_id = 0;
556 | + int status = 1;
557 | +#endif
558 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
559 | + if (susfs_sus_mount(mnt, &p->root))
560 | + return 0;
561 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
562 | + if (!uid_matches_proc_need_to_reorder_mnt_id())
563 | + goto orig_flow;
564 | + status = susfs_get_fake_mnt_id(r->mnt_id, &out_mnt_id, &out_parent_mnt_id);
565 | + if (status)
566 | + goto orig_flow;
567 | + seq_printf(m, "%i %i %u:%u ", out_mnt_id, out_parent_mnt_id,
568 | + MAJOR(sb->s_dev), MINOR(sb->s_dev));
569 | + goto bypass_orig_flow;
570 | +orig_flow:
571 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
572 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
573 | seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
574 | MAJOR(sb->s_dev), MINOR(sb->s_dev));
575 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
576 | +bypass_orig_flow:
577 | +#endif
578 | +
579 | if (sb->s_op->show_path) {
580 | err = sb->s_op->show_path(m, mnt->mnt_root);
581 | if (err)
582 | @@ -202,6 +234,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
583 | struct super_block *sb = mnt_path.dentry->d_sb;
584 | int err;
585 |
586 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
587 | + if (susfs_sus_mount(mnt, &p->root))
588 | + return 0;
589 | +#endif
590 | +
591 | /* device */
592 | if (sb->s_op->show_devname) {
593 | seq_puts(m, "device ");
594 | @@ -285,6 +322,12 @@ static int mounts_open_common(struct inode *inode, struct file *file,
595 | p->show = show;
596 | p->cached_event = ~0ULL;
597 |
598 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
599 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
600 | + susfs_add_mnt_id_recorder(p->ns);
601 | + }
602 | +#endif
603 | +
604 | return 0;
605 |
606 | err_put_path:
607 | @@ -299,6 +342,13 @@ static int mounts_release(struct inode *inode, struct file *file)
608 | {
609 | struct seq_file *m = file->private_data;
610 | struct proc_mounts *p = m->private;
611 | +
612 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
613 | + if (uid_matches_proc_need_to_reorder_mnt_id()) {
614 | + susfs_remove_mnt_id_recorder();
615 | + }
616 | +#endif
617 | +
618 | path_put(&p->root);
619 | put_mnt_ns(p->ns);
620 | return seq_release_private(inode, file);
621 | diff --git a/fs/readdir.c b/fs/readdir.c
622 | index 07a3b5baa404..a3d709fa5312 100644
623 | --- a/fs/readdir.c
624 | +++ b/fs/readdir.c
625 | @@ -22,6 +22,10 @@
626 | #include
627 | #include
628 |
629 | +#ifdef CONFIG_KSU_SUSFS
630 | +#include
631 | +#endif
632 | +
633 | #include
634 |
635 | /*
636 | @@ -328,6 +332,11 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
637 | prev_reclen = buf->prev_reclen;
638 | if (prev_reclen && signal_pending(current))
639 | return -EINTR;
640 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
641 | + if (susfs_sus_ino_for_filldir64(ino)) {
642 | + return 0;
643 | + }
644 | +#endif
645 | dirent = buf->current_dir;
646 | prev = (void __user *)dirent - prev_reclen;
647 | if (!user_access_begin(prev, reclen + prev_reclen))
648 | diff --git a/fs/stat.c b/fs/stat.c
649 | index 298eb77668a7..974424e01653 100644
650 | --- a/fs/stat.c
651 | +++ b/fs/stat.c
652 | @@ -21,6 +21,10 @@
653 | #include
654 | #include
655 |
656 | +#ifdef CONFIG_KSU_SUSFS
657 | +#include
658 | +#endif
659 | +
660 | /**
661 | * generic_fillattr - Fill in the basic attributes from the inode struct
662 | * @inode: Inode to use as the source
663 | @@ -112,6 +116,12 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
664 | {
665 | int retval;
666 |
667 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
668 | + if (susfs_sus_path_by_path(path, &retval, SYSCALL_FAMILY_ALL_ENOENT)) {
669 | + return retval;
670 | + }
671 | +#endif
672 | +
673 | retval = security_inode_getattr(path);
674 | if (retval)
675 | return retval;
676 | @@ -330,6 +340,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
677 | #endif
678 | tmp.st_blocks = stat->blocks;
679 | tmp.st_blksize = stat->blksize;
680 | +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
681 | + susfs_sus_kstat(tmp.st_ino, &tmp);
682 | +#endif
683 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
684 | }
685 |
686 | diff --git a/kernel/sys.c b/kernel/sys.c
687 | index 125edee69eed..3c3d4f4680a1 100644
688 | --- a/kernel/sys.c
689 | +++ b/kernel/sys.c
690 | @@ -75,6 +75,10 @@
691 |
692 | #include "uid16.h"
693 |
694 | +#ifdef CONFIG_KSU_SUSFS
695 | +#include
696 | +#endif
697 | +
698 | #include
699 |
700 | #ifndef SET_UNALIGN_CTL
701 | @@ -1247,6 +1251,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
702 | down_read(&uts_sem);
703 | memcpy(&tmp, utsname(), sizeof(tmp));
704 | up_read(&uts_sem);
705 | +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
706 | + susfs_spoof_uname(&tmp);
707 | +#endif
708 | if (copy_to_user(name, &tmp, sizeof(tmp)))
709 | return -EFAULT;
710 |
711 | diff --git a/mm/memfd.c b/mm/memfd.c
712 | index fae4142f7d25..093d9b041d46 100644
713 | --- a/mm/memfd.c
714 | +++ b/mm/memfd.c
715 | @@ -20,6 +20,10 @@
716 | #include
717 | #include
718 |
719 | +#ifdef CONFIG_KSU_SUSFS
720 | +#include
721 | +#endif
722 | +
723 | /*
724 | * We need a tag: a new tag would expand every xa_node by 8 bytes,
725 | * so reuse a tag which we firmly believe is never set or cleared on tmpfs
726 | @@ -306,6 +310,13 @@ SYSCALL_DEFINE2(memfd_create,
727 | goto err_name;
728 | }
729 |
730 | +#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
731 | + if (susfs_sus_memfd(name)) {
732 | + error = -EFAULT;
733 | + goto err_name;
734 | + }
735 | +#endif
736 | +
737 | fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0);
738 | if (fd < 0) {
739 | error = fd;
740 |
--------------------------------------------------------------------------------
/kernel_patches/KernelSU/10_enable_susfs_for_ksu.patch:
--------------------------------------------------------------------------------
1 | diff --git a/kernel/Kconfig b/kernel/Kconfig
2 | index 67f177f4..27cc7b1e 100644
3 | --- a/kernel/Kconfig
4 | +++ b/kernel/Kconfig
5 | @@ -16,4 +16,87 @@ config KSU_DEBUG
6 | help
7 | Enable KernelSU debug mode.
8 |
9 | +menu "KernelSU - SUSFS"
10 | +config KSU_SUSFS
11 | + bool "KernelSU addon - SUSFS"
12 | + depends on KSU
13 | + default y
14 | + help
15 | + Patch and Enable SUSFS to kernel with KernelSU
16 | +
17 | +config KSU_SUSFS_SUS_PATH
18 | + bool "Enable to hide suspicious path"
19 | + depends on KSU_SUSFS
20 | + default y
21 | + help
22 | + Allow hiding the existence of user-defined file/directory from various system calls
23 | +
24 | +config KSU_SUSFS_SUS_MOUNT
25 | + bool "Enable to hide suspicious mounts"
26 | + depends on KSU_SUSFS
27 | + default y
28 | + help
29 | + Allow hiding the user-defined mount paths from /proc/self/[mounts|mountinfo|mountstat]
30 | +
31 | +config KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
32 | + bool "Enable to re-order mount id and parent mount id in mountinfo (experimental)"
33 | + depends on KSU_SUSFS_SUS_MOUNT
34 | + default n
35 | + help
36 | + - Enable this option will automatically and completely re-order the mount id and parent mount id in /proc/self/mountinfo
37 | + - The actual mnt_id/parent_mnt_id is not changed in kernel, only reflects on /proc/self/mountinfo
38 | + - You should not enable this if the mnt_id on your device is already not in order by default
39 | + - Moreover, be careful this feature may cause unknown system crashes / random reboot / bootloop on different kernels or devices, further testing is needed.
40 | + - Requires KSU_SUSFS_SUS_MOUNT to be ON
41 | +
42 | +config KSU_SUSFS_SUS_KSTAT
43 | + bool "Enable to spoof suspicious kstat"
44 | + depends on KSU_SUSFS
45 | + default y
46 | + help
47 | + Allow spoofing the kstat of user-defined file/directory
48 | +
49 | +config KSU_SUSFS_SUS_MAPS
50 | + bool "Enable to spoof suspicious maps"
51 | + depends on KSU_SUSFS
52 | + default y
53 | + help
54 | + Allow spoofing the user-defined mappings in /proc/self/[maps|smaps|map_files]
55 | +
56 | +config KSU_SUSFS_SUS_PROC_FD_LINK
57 | + bool "Enable to spoof suspicous symbolic links (experimental)"
58 | + depends on KSU_SUSFS
59 | + default n
60 | + help
61 | + Allow spoofing the user-defined symbolic link in /proc/self/fd/
62 | +
63 | +config KSU_SUSFS_SUS_MEMFD
64 | + bool "Enable to hide or spoof suspicous memfd (experimental)"
65 | + depends on KSU_SUSFS
66 | + default n
67 | + help
68 | + Allow preventing the user-defined memfd name from being created
69 | +
70 | +config KSU_SUSFS_TRY_UMOUNT
71 | + bool "Enable to use ksu's try_umount"
72 | + depends on KSU_SUSFS
73 | + default y
74 | + help
75 | + Allow using ksu's umount to umount other user-defined mount paths prior to ksu's default umount paths
76 | +
77 | +config KSU_SUSFS_SPOOF_UNAME
78 | + bool "Enable to spoof uname"
79 | + depends on KSU_SUSFS
80 | + default y
81 | + help
82 | + Allow spoofing the string returned by uname syscall to user-defined string
83 | +
84 | +config KSU_SUSFS_ENABLE_LOG
85 | + bool "Enable logging susfs log to kernel"
86 | + depends on KSU_SUSFS
87 | + default y
88 | + help
89 | + Allow logging susfs log to kernel, uncheck it to completely disable all susfs log
90 | +endmenu
91 | +
92 | endmenu
93 | diff --git a/kernel/Makefile b/kernel/Makefile
94 | index 66929756..d25f36c7 100644
95 | --- a/kernel/Makefile
96 | +++ b/kernel/Makefile
97 | @@ -66,4 +66,43 @@ endif
98 | ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
99 | ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
100 |
101 | +ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
102 | +ifdef KSU_SUSFS
103 | +ccflags-y += -DKSU_SUSFS
104 | +endif
105 | +ifdef KSU_SUSFS_SUS_PATH
106 | +ccflags-y += -DKSU_SUSFS_SUS_PATH
107 | +endif
108 | +ifdef KSU_SUSFS_SUS_MOUNT
109 | +ccflags-y += -DKSU_SUSFS_SUS_MOUNT
110 | +endif
111 | +ifdef KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
112 | +ccflags-y += -DKSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
113 | +endif
114 | +ifdef KSU_SUSFS_SUS_KSTAT
115 | +ccflags-y += -DKSU_SUSFS_SUS_KSTAT
116 | +endif
117 | +ifdef KSU_SUSFS_SUS_MAPS
118 | +ccflags-y += -DKSU_SUSFS_SUS_MAPS
119 | +endif
120 | +ifdef KSU_SUSFS_SUS_PROC_FD_LINK
121 | +ccflags-y += -DKSU_SUSFS_SUS_PROC_FD_LINK
122 | +endif
123 | +ifdef KSU_SUSFS_SUS_MEMFD
124 | +ccflags-y += -DKSU_SUSFS_SUS_MEMFD
125 | +endif
126 | +ifdef KSU_SUSFS_TRY_UMOUNT
127 | +ccflags-y += -DKSU_SUSFS_TRY_UMOUNT
128 | +endif
129 | +ifdef KSU_SUSFS_SPOOF_UNAME
130 | +ccflags-y += -DKSU_SUSFS_SPOOF_UNAME
131 | +endif
132 | +ifdef KSU_SUSFS_ENABLE_LOG
133 | +ccflags-y += -DKSU_SUSFS_ENABLE_LOG
134 | +endif
135 | +else
136 | +$(info -- You have not integrate susfs in your kernel.)
137 | +$(info -- Read: https://gitlab.com/simonpunk/susfs4ksu)
138 | +endif
139 | +
140 | # Keep a new line here!! Because someone may append config
141 | diff --git a/kernel/core_hook.c b/kernel/core_hook.c
142 | index 429ba330..f016db75 100644
143 | --- a/kernel/core_hook.c
144 | +++ b/kernel/core_hook.c
145 | @@ -44,6 +44,10 @@
146 | #include "throne_tracker.h"
147 | #include "kernel_compat.h"
148 |
149 | +#ifdef CONFIG_KSU_SUSFS
150 | +#include
151 | +#endif
152 | +
153 | static bool ksu_module_mounted = false;
154 |
155 | extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
156 | @@ -375,6 +379,207 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
157 | return 0;
158 | }
159 |
160 | +#ifdef CONFIG_KSU_SUSFS
161 | + if (current_uid().val == 0) {
162 | + int error = 0;
163 | +#ifdef CONFIG_KSU_SUSFS_SUS_PATH
164 | + if (arg2 == CMD_SUSFS_ADD_SUS_PATH) {
165 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_path))) {
166 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg3 is not accessible\n");
167 | + return 0;
168 | + }
169 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
170 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg5 is not accessible\n");
171 | + return 0;
172 | + }
173 | + error = susfs_add_sus_path((struct st_susfs_sus_path __user*)arg3);
174 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH -> ret: %d\n", error);
175 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
176 | + return 0;
177 | + }
178 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
179 | +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
180 | + if (arg2 == CMD_SUSFS_ADD_SUS_MOUNT) {
181 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_mount))) {
182 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg3 is not accessible\n");
183 | + return 0;
184 | + }
185 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
186 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg5 is not accessible\n");
187 | + return 0;
188 | + }
189 | + error = susfs_add_sus_mount((struct st_susfs_sus_mount __user*)arg3);
190 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> ret: %d\n", error);
191 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
192 | + return 0;
193 | + }
194 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
195 | +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
196 | + if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT) {
197 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
198 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg3 is not accessible\n");
199 | + return 0;
200 | + }
201 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
202 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg5 is not accessible\n");
203 | + return 0;
204 | + }
205 | + error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
206 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> ret: %d\n", error);
207 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
208 | + return 0;
209 | + }
210 | + if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) {
211 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
212 | + pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg3 is not accessible\n");
213 | + return 0;
214 | + }
215 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
216 | + pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg5 is not accessible\n");
217 | + return 0;
218 | + }
219 | + error = susfs_update_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
220 | + pr_info("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> ret: %d\n", error);
221 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
222 | + return 0;
223 | + }
224 | + if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
225 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
226 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg3 is not accessible\n");
227 | + return 0;
228 | + }
229 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
230 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg5 is not accessible\n");
231 | + return 0;
232 | + }
233 | + error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
234 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> ret: %d\n", error);
235 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
236 | + return 0;
237 | + }
238 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
239 | +#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
240 | + if (arg2 == CMD_SUSFS_ADD_SUS_MAPS) {
241 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
242 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS -> arg3 is not accessible\n");
243 | + return 0;
244 | + }
245 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
246 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS -> arg5 is not accessible\n");
247 | + return 0;
248 | + }
249 | + error = susfs_add_sus_maps((struct st_susfs_sus_maps __user*)arg3);
250 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_MAPS -> ret: %d\n", error);
251 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
252 | + return 0;
253 | + }
254 | + if (arg2 == CMD_SUSFS_UPDATE_SUS_MAPS) {
255 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
256 | + pr_err("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> arg3 is not accessible\n");
257 | + return 0;
258 | + }
259 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
260 | + pr_err("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> arg5 is not accessible\n");
261 | + return 0;
262 | + }
263 | + error = susfs_update_sus_maps((struct st_susfs_sus_maps __user*)arg3);
264 | + pr_info("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> ret: %d\n", error);
265 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
266 | + return 0;
267 | + }
268 | + if (arg2 == CMD_SUSFS_ADD_SUS_MAPS_STATICALLY) {
269 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
270 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> arg3 is not accessible\n");
271 | + return 0;
272 | + }
273 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
274 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> arg5 is not accessible\n");
275 | + return 0;
276 | + }
277 | + error = susfs_add_sus_maps((struct st_susfs_sus_maps __user*)arg3);
278 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> ret: %d\n", error);
279 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
280 | + return 0;
281 | + }
282 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
283 | +#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
284 | + if (arg2 == CMD_SUSFS_ADD_SUS_PROC_FD_LINK) {
285 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_proc_fd_link))) {
286 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> arg3 is not accessible\n");
287 | + return 0;
288 | + }
289 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
290 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> arg5 is not accessible\n");
291 | + return 0;
292 | + }
293 | + error = susfs_add_sus_proc_fd_link((struct st_susfs_sus_proc_fd_link __user*)arg3);
294 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> ret: %d\n", error);
295 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
296 | + return 0;
297 | + }
298 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
299 | +#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
300 | + if (arg2 == CMD_SUSFS_ADD_SUS_MEMFD) {
301 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_memfd))) {
302 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> arg3 is not accessible\n");
303 | + return 0;
304 | + }
305 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
306 | + pr_err("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> arg5 is not accessible\n");
307 | + return 0;
308 | + }
309 | + error = susfs_add_sus_memfd((struct st_susfs_sus_memfd __user*)arg3);
310 | + pr_info("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> ret: %d\n", error);
311 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
312 | + return 0;
313 | + }
314 | +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
315 | +#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
316 | + if (arg2 == CMD_SUSFS_ADD_TRY_UMOUNT) {
317 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_try_umount))) {
318 | + pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg3 is not accessible\n");
319 | + return 0;
320 | + }
321 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
322 | + pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg5 is not accessible\n");
323 | + return 0;
324 | + }
325 | + error = susfs_add_try_umount((struct st_susfs_try_umount __user*)arg3);
326 | + pr_info("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> ret: %d\n", error);
327 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
328 | + return 0;
329 | + }
330 | +#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
331 | +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
332 | + if (arg2 == CMD_SUSFS_SET_UNAME) {
333 | + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_uname))) {
334 | + pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg3 is not accessible\n");
335 | + return 0;
336 | + }
337 | + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
338 | + pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg5 is not accessible\n");
339 | + return 0;
340 | + }
341 | + error = susfs_set_uname((struct st_susfs_uname __user*)arg3);
342 | + pr_info("susfs: CMD_SUSFS_SET_UNAME -> ret: %d\n", error);
343 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
344 | + return 0;
345 | + }
346 | +#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
347 | +#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
348 | + if (arg2 == CMD_SUSFS_ENABLE_LOG) {
349 | + if (arg3 != 0 && arg3 != 1) {
350 | + pr_err("susfs: CMD_SUSFS_ENABLE_LOG -> arg3 can only be 0 or 1\n");
351 | + return 0;
352 | + }
353 | + susfs_set_log(arg3);
354 | + copy_to_user((void __user*)arg5, &error, sizeof(error));
355 | + return 0;
356 | + }
357 | +#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
358 | + }
359 | +#endif //#ifdef CONFIG_KSU_SUSFS
360 | +
361 | // all other cmds are for 'root manager'
362 | if (!from_manager) {
363 | return 0;
364 | @@ -535,6 +740,11 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
365 | current->pid);
366 | #endif
367 |
368 | +#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
369 | + // susfs come first, and lastly umount by ksu, make sure umount in reversed order
370 | + susfs_try_umount(new_uid.val);
371 | +#endif
372 | +
373 | // fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
374 | // filter the mountpoint whose target is `/data/adb`
375 | try_umount("/system", true, 0);
376 | diff --git a/kernel/kernel_compat.c b/kernel/kernel_compat.c
377 | index b242bc63..0ec3df62 100644
378 | --- a/kernel/kernel_compat.c
379 | +++ b/kernel/kernel_compat.c
380 | @@ -77,6 +77,16 @@ void ksu_android_ns_fs_check()
381 | task_unlock(current);
382 | }
383 |
384 | +int ksu_access_ok(const void *addr, unsigned long size) {
385 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
386 | + /* For kernels before 5.0.0, pass the type argument to access_ok. */
387 | + return access_ok(VERIFY_READ, addr, size);
388 | +#else
389 | + /* For kernels 5.0.0 and later, ignore the type argument. */
390 | + return access_ok(addr, size);
391 | +#endif
392 | +}
393 | +
394 | struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
395 | {
396 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI)
397 | diff --git a/kernel/kernel_compat.h b/kernel/kernel_compat.h
398 | index ba998185..34050e73 100644
399 | --- a/kernel/kernel_compat.h
400 | +++ b/kernel/kernel_compat.h
401 | @@ -29,6 +29,7 @@ extern struct key *init_session_keyring;
402 | #endif
403 |
404 | extern void ksu_android_ns_fs_check();
405 | +extern int ksu_access_ok(const void *addr, unsigned long size);
406 | extern struct file *ksu_filp_open_compat(const char *filename, int flags,
407 | umode_t mode);
408 | extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
409 | diff --git a/kernel/ksu.c b/kernel/ksu.c
410 | index 3639edc2..4a9cfaba 100644
411 | --- a/kernel/ksu.c
412 | +++ b/kernel/ksu.c
413 | @@ -11,6 +11,10 @@
414 | #include "ksu.h"
415 | #include "throne_tracker.h"
416 |
417 | +#ifdef CONFIG_KSU_SUSFS
418 | +#include
419 | +#endif
420 | +
421 | static struct workqueue_struct *ksu_workqueue;
422 |
423 | bool ksu_queue_work(struct work_struct *work)
424 | @@ -49,6 +53,10 @@ int __init kernelsu_init(void)
425 | pr_alert("*************************************************************");
426 | #endif
427 |
428 | +#ifdef CONFIG_KSU_SUSFS
429 | + susfs_init();
430 | +#endif
431 | +
432 | ksu_core_init();
433 |
434 | ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0);
435 | diff --git a/kernel/selinux/rules.c b/kernel/selinux/rules.c
436 | index 1ba6d853..7b24203c 100644
437 | --- a/kernel/selinux/rules.c
438 | +++ b/kernel/selinux/rules.c
439 | @@ -134,6 +134,11 @@ void apply_kernelsu_rules()
440 | ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
441 | ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
442 |
443 | +#ifdef CONFIG_KSU_SUSFS
444 | + // Allow umount in zygote process without installing zygisk
445 | + ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
446 | +#endif
447 | +
448 | rcu_read_unlock();
449 | }
450 |
451 |
--------------------------------------------------------------------------------
/kernel_patches/include/linux/susfs.h:
--------------------------------------------------------------------------------
1 | #ifndef KSU_SUSFS_H
2 | #define KSU_SUSFS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | /* shared with userspace ksu_susfs tool */
10 | #define CMD_SUSFS_ADD_SUS_PATH 0x55555
11 | #define CMD_SUSFS_ADD_SUS_MOUNT 0x55556
12 | #define CMD_SUSFS_ADD_SUS_KSTAT 0x55558
13 | #define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55559
14 | #define CMD_SUSFS_ADD_TRY_UMOUNT 0x5555a
15 | #define CMD_SUSFS_SET_UNAME 0x5555b
16 | #define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x5555c
17 | #define CMD_SUSFS_ENABLE_LOG 0x5555d
18 | #define CMD_SUSFS_ADD_SUS_MAPS_STATICALLY 0x5555e
19 | #define CMD_SUSFS_ADD_SUS_PROC_FD_LINK 0x5555f
20 | #define CMD_SUSFS_ADD_SUS_MAPS 0x55560
21 | #define CMD_SUSFS_UPDATE_SUS_MAPS 0x55561
22 | #define CMD_SUSFS_ADD_SUS_MEMFD 0x55562
23 |
24 | #define SUSFS_MAX_LEN_PATHNAME 256 // 256 should address many paths already unless you are doing some strange experimental stuff, then set your own desired length
25 | #define SUSFS_MAX_LEN_MFD_NAME 248
26 | #define SUSFS_MAX_SUS_MNTS 300 // I think 300 is now enough? This includes the mount entries for each process and sus mounts added by user
27 | #define SUSFS_MAX_SUS_MAPS 200 // I think 200 is now enough? Tell me why if you have over 200 entries
28 |
29 | #define SUSFS_MAP_FILES_ACTION_REMOVE_WRITE_PERM 1
30 | #define SUSFS_MAP_FILES_ACTION_HIDE_DENTRY 2
31 |
32 | /* non shared to userspace ksu_susfs tool */
33 | #define SYSCALL_FAMILY_ALL_ENOENT 0
34 | #define SYSCALL_FAMILY_OPENAT 1
35 | #define SYSCALL_FAMILY_MKNOD 2
36 | #define SYSCALL_FAMILY_MKDIRAT 3
37 | #define SYSCALL_FAMILY_RMDIR 4
38 | #define SYSCALL_FAMILY_UNLINKAT 5
39 | #define SYSCALL_FAMILY_SYMLINKAT_NEWNAME 6
40 | #define SYSCALL_FAMILY_LINKAT_OLDNAME 7
41 | #define SYSCALL_FAMILY_LINKAT_NEWNAME 8
42 | #define SYSCALL_FAMILY_RENAMEAT2_OLDNAME 9
43 | #define SYSCALL_FAMILY_RENAMEAT2_NEWNAME 10
44 | #define SYSCALL_FAMILY_TRUNCATE 11
45 | #define SYSCALL_FAMILY_FACCESSAT 12
46 | #define SYSCALL_FAMILY_CHDIR 13
47 |
48 | #define getname_safe(name) (name == NULL ? ERR_PTR(-EINVAL) : getname(name))
49 | #define putname_safe(name) (IS_ERR(name) ? NULL : putname(name))
50 |
51 | #define uid_matches_suspicious_path() (current_uid().val >= 2000)
52 | #define uid_matches_suspicious_kstat() (current_uid().val >= 2000)
53 | #define uid_matches_proc_need_to_reorder_mnt_id() (current_uid().val >= 10000)
54 |
55 | struct st_susfs_sus_path {
56 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
57 | unsigned long target_ino;
58 | };
59 |
60 | struct st_susfs_sus_mount {
61 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
62 | };
63 |
64 | struct st_susfs_sus_kstat {
65 | unsigned long target_ino; // the ino after bind mounted or overlayed
66 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
67 | char spoofed_pathname[SUSFS_MAX_LEN_PATHNAME];
68 | unsigned long spoofed_ino;
69 | unsigned long spoofed_dev;
70 | unsigned int spoofed_nlink;
71 | long spoofed_atime_tv_sec;
72 | long spoofed_mtime_tv_sec;
73 | long spoofed_ctime_tv_sec;
74 | long spoofed_atime_tv_nsec;
75 | long spoofed_mtime_tv_nsec;
76 | long spoofed_ctime_tv_nsec;
77 | };
78 |
79 | struct st_susfs_sus_maps {
80 | bool is_statically;
81 | int compare_mode;
82 | bool is_isolated_entry;
83 | bool is_file;
84 | unsigned long prev_target_ino;
85 | unsigned long next_target_ino;
86 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
87 | unsigned long target_ino;
88 | unsigned long target_dev;
89 | unsigned long long target_pgoff;
90 | unsigned long target_prot;
91 | unsigned long target_addr_size;
92 | char spoofed_pathname[SUSFS_MAX_LEN_PATHNAME];
93 | unsigned long spoofed_ino;
94 | unsigned long spoofed_dev;
95 | unsigned long long spoofed_pgoff;
96 | unsigned long spoofed_prot;
97 | bool need_to_spoof_pathname;
98 | bool need_to_spoof_ino;
99 | bool need_to_spoof_dev;
100 | bool need_to_spoof_pgoff;
101 | bool need_to_spoof_prot;
102 | };
103 |
104 | struct st_susfs_try_umount {
105 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
106 | int mnt_mode;
107 | };
108 |
109 | struct st_susfs_sus_proc_fd_link {
110 | char target_link_name[SUSFS_MAX_LEN_PATHNAME];
111 | char spoofed_link_name[SUSFS_MAX_LEN_PATHNAME];
112 | };
113 |
114 | struct st_susfs_sus_memfd {
115 | char target_pathname[SUSFS_MAX_LEN_MFD_NAME];
116 | };
117 |
118 | struct st_susfs_mnt_id_recorder {
119 | int target_mnt_id[SUSFS_MAX_SUS_MNTS];
120 | int spoofed_mnt_id[SUSFS_MAX_SUS_MNTS];
121 | int spoofed_parent_mnt_id[SUSFS_MAX_SUS_MNTS];
122 | int count;
123 | };
124 |
125 | struct st_susfs_sus_path_list {
126 | struct list_head list;
127 | struct st_susfs_sus_path info;
128 | };
129 |
130 | struct st_susfs_sus_mount_list {
131 | struct list_head list;
132 | struct st_susfs_sus_mount info;
133 | };
134 |
135 | struct st_susfs_sus_kstat_list {
136 | struct list_head list;
137 | struct st_susfs_sus_kstat info;
138 | };
139 |
140 | struct st_susfs_sus_maps_list {
141 | struct list_head list;
142 | struct st_susfs_sus_maps info;
143 | };
144 |
145 | struct st_susfs_try_umount_list {
146 | struct list_head list;
147 | struct st_susfs_try_umount info;
148 | };
149 |
150 | struct st_susfs_sus_proc_fd_link_list {
151 | struct list_head list;
152 | struct st_susfs_sus_proc_fd_link info;
153 | };
154 |
155 | struct st_susfs_sus_memfd_list {
156 | struct list_head list;
157 | struct st_susfs_sus_memfd info;
158 | };
159 |
160 | struct st_susfs_mnt_id_recorder_list {
161 | struct list_head list;
162 | int pid;
163 | int opened_count;
164 | struct st_susfs_mnt_id_recorder info;
165 | };
166 |
167 | struct st_susfs_uname {
168 | char sysname[__NEW_UTS_LEN+1];
169 | char nodename[__NEW_UTS_LEN+1];
170 | char release[__NEW_UTS_LEN+1];
171 | char version[__NEW_UTS_LEN+1];
172 | char machine[__NEW_UTS_LEN+1];
173 | };
174 |
175 | int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info);
176 | int susfs_add_sus_mount(struct st_susfs_sus_mount* __user user_info);
177 | int susfs_add_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
178 | int susfs_update_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
179 | int susfs_add_sus_maps(struct st_susfs_sus_maps* __user user_info);
180 | int susfs_update_sus_maps(struct st_susfs_sus_maps* __user user_info);
181 | int susfs_add_sus_proc_fd_link(struct st_susfs_sus_proc_fd_link* __user user_info);
182 | int susfs_add_sus_memfd(struct st_susfs_sus_memfd* __user user_info);
183 | int susfs_add_try_umount(struct st_susfs_try_umount* __user user_info);
184 | int susfs_set_uname(struct st_susfs_uname* __user user_info);
185 |
186 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
187 | int susfs_sus_path_by_path(struct path* file, int* errno_to_be_changed, int syscall_family);
188 | #else
189 | int susfs_sus_path_by_path(const struct path* file, int* errno_to_be_changed, int syscall_family);
190 | #endif
191 | int susfs_sus_path_by_filename(struct filename* name, int* errno_to_be_changed, int syscall_family);
192 | int susfs_sus_mount(struct vfsmount* mnt, struct path* root);
193 | int susfs_sus_ino_for_filldir64(unsigned long ino);
194 | void susfs_sus_kstat(unsigned long ino, struct stat* out_stat);
195 | int susfs_sus_maps(unsigned long target_ino, unsigned long target_addr_size,
196 | unsigned long* orig_ino, dev_t* orig_dev, vm_flags_t* flags,
197 | unsigned long long* pgoff, struct vm_area_struct* vma, char* out_name);
198 | void susfs_sus_map_files_readlink(unsigned long target_ino, char* pathname);
199 | int susfs_sus_map_files_instantiate(struct vm_area_struct* vma);
200 | int susfs_is_sus_maps_list_empty(void);
201 | int susfs_sus_proc_fd_link(char *pathname, int len);
202 | int susfs_is_sus_proc_fd_link_list_empty(void);
203 | int susfs_sus_memfd(char *memfd_name);
204 | void susfs_try_umount(uid_t target_uid);
205 | void susfs_spoof_uname(struct new_utsname* tmp);
206 | void susfs_add_mnt_id_recorder(struct mnt_namespace *ns);
207 | int susfs_get_fake_mnt_id(int mnt_id, int *out_mnt_id, int *out_parent_mnt_id);
208 | void susfs_remove_mnt_id_recorder(void);
209 |
210 | void susfs_set_log(bool enabled);
211 |
212 | void susfs_change_error_no_by_pathname(char* pathname, int* errno_to_be_changed, int syscall_family);
213 |
214 | void __init susfs_init(void);
215 |
216 | #endif
217 |
--------------------------------------------------------------------------------
/ksu_module_susfs/META-INF/com/google/android/update-binary:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 |
3 | #################
4 | # Initialization
5 | #################
6 |
7 | umask 022
8 |
9 | # echo before loading util_functions
10 | ui_print() { echo "$1"; }
11 |
12 | require_new_magisk() {
13 | ui_print "*******************************"
14 | ui_print " Please install Magisk v20.4+! "
15 | ui_print "*******************************"
16 | exit 1
17 | }
18 |
19 | #########################
20 | # Load util_functions.sh
21 | #########################
22 |
23 | OUTFD=$2
24 | ZIPFILE=$3
25 |
26 | mount /data 2>/dev/null
27 |
28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
29 | . /data/adb/magisk/util_functions.sh
30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
31 |
32 | install_module
33 | exit 0
34 |
--------------------------------------------------------------------------------
/ksu_module_susfs/META-INF/com/google/android/updater-script:
--------------------------------------------------------------------------------
1 | #MAGISK
--------------------------------------------------------------------------------
/ksu_module_susfs/README.md:
--------------------------------------------------------------------------------
1 | ## A KernelSU module for SUS-FS patched kernel ##
2 |
3 | This module is used for installing a userspace helper tool called **ksu_susfs** into /data/adb/ and provides a script example to communicate with SUS-FS kernel
4 |
5 |
--------------------------------------------------------------------------------
/ksu_module_susfs/customize.sh:
--------------------------------------------------------------------------------
1 |
2 | SUSFS_BIN_ARM64=${TMPDIR}/susfs/tools/ksu_susfs_arm64
3 | SUSFS_BIN_ARM=${TMPDIR}/susfs/tools/ksu_susfs_arm
4 |
5 | DEST_BIN_DIR=/data/adb/ksu/bin
6 | DEST_BIN_PATH=${DEST_BIN_DIR}/ksu_susfs
7 |
8 | if [ ! -d ${DEST_BIN_DIR} ]; then
9 | ui_print "'${DEST_BIN_DIR}' not existed, installation aborted."
10 | rm -rf ${MODPATH}
11 | exit 1
12 | fi
13 |
14 | unzip ${ZIPFILE} -d ${TMPDIR}/susfs
15 |
16 | if [ ${ARCH} = "arm64" ]; then
17 | ui_print "copying ${SUSFS_BIN_ARM64} to ${DEST_BIN_PATH}"
18 | cp ${SUSFS_BIN_ARM64} ${DEST_BIN_PATH}
19 | elif [ ${ARCH} = "arm" ]; then
20 | ui_print "copying ${SUSFS_BIN_ARM} to ${DEST_BIN_PATH}"
21 | cp ${SUSFS_BIN_ARM} ${DEST_BIN_PATH}
22 | fi
23 |
24 | chmod 755 ${DEST_BIN_PATH}
25 | chmod 644 ${MODPATH}/post-fs-data.sh
26 | chmod 644 ${MODPATH}/service.sh
27 | chmod 644 ${MODPATH}/uninstall.sh
28 |
29 |
30 | rm -rf ${MODPATH}/tools
31 | rm ${MODPATH}/customize.sh ${MODPATH}/README.md
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ksu_module_susfs/module.prop:
--------------------------------------------------------------------------------
1 | id=susfs4ksu
2 | name=SUSFS-FOR-KERNELSU
3 | version=v1.3.8
4 | versionCode=103008
5 | author=simonpunk@gitlab.com
6 | description=An addon root hiding service for KernelSU compiled with patched kernel source.
7 |
8 |
--------------------------------------------------------------------------------
/ksu_module_susfs/post-fs-data.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 |
3 | MODDIR=${0%/*}
4 |
5 | SUSFS_BIN=/data/adb/ksu/bin/ksu_susfs
6 |
7 | ## Important Notes:
8 | ## - The following command can be run at other stages like service.sh, boot-completed.sh etc..,
9 | ## - This module is just an demo showing how to use ksu_susfs tool to commuicate with kernel
10 |
11 | #### For some custom ROM ####
12 | cat </dev/null
13 | ${SUSFS_BIN} add_sus_path /system/addon.d
14 | ${SUSFS_BIN} add_sus_path /data/adbroot
15 | ${SUSFS_BIN} add_sus_path /vendor/bin/install-recovery.sh
16 | ${SUSFS_BIN} add_sus_path /system/bin/install-recovery.sh
17 | EOF
18 |
19 | #### Trying to hide the mounted path in /proc/self/[mounts|mountstat|mountinfo] for all processes ####
20 | cat </dev/null
21 | ${SUSFS_BIN} add_sus_mount /system/apex/com.android.art/bin/dex2oat
22 | ${SUSFS_BIN} add_sus_mount /apex/com.android.art/bin/dex2oat
23 | ${SUSFS_BIN} add_sus_mount /apex/com.android.art/bin/dex2oat32
24 | ${SUSFS_BIN} add_sus_mount /apex/com.android.art/bin/dex2oat64
25 | EOF
26 |
27 | #### Always umount /system/etc/hosts if hosts module is used ####
28 | ## Note that susfs's try_umount takes precedence of ksu's try_umount ##
29 | ## Also, umount can be detected in ksu, or try using add_sus_mount instead ##
30 | cat </dev/null
31 | ${SUSFS_BIN} add_try_umount /system/etc/hosts '1'
32 | EOF
33 |
34 | #### Spoof the uname ####
35 | cat </dev/null
36 | ${SUSFS_BIN} set_uname 'default' 'default' '4.9.337-g3291538446b7' 'default' 'default'
37 | EOF
38 |
39 | #### Enable / Disable susfs logging to kernel, 0 -> disable, 1 -> enable ####
40 | cat </dev/null
41 | ${SUSFS_BIN} enable_log 0
42 | EOF
43 |
44 | #### To spoof the stat of file/directory statically ####
45 | cat </dev/null
46 | ${SUSFS_BIN} add_sus_kstat_statically '/system/framework/services.jar' 'default' 'default' 'default' '1230768000' '0' '1230768000' '0' '1230768000' '0'
47 | EOF
48 |
49 | #### To spoof the stat of file/directory dynamically ####
50 | cat </dev/null
51 | ## First, before bind mount your file/directory, use 'add_sus_kstat' to add the path
52 | ${SUSFS_BIN} add_sus_kstat '/system/etc/hosts'
53 |
54 | ## Now bind mount or overlay your path
55 | mount --bind "$MODDIR/hosts" /system/etc/hosts
56 |
57 | ## Finally use 'update_sus_kstat' to update the path again for the changed ino and device number
58 | ${SUSFS_BIN} update_sus_kstat '/system/etc/hosts'
59 | EOF
60 |
61 | #### To spoof only the ino and dev in /proc/self/[maps|smaps] dynamically ####
62 | cat </dev/null
63 | ${SUSFS_BIN} add_sus_maps ${SPOOFED_PATHNAME}
64 | mount --bind "$MODDIR/hosts" /system/etc/hosts
65 | ${SUSFS_BIN} update_sus_maps ${SPOOFED_PATHNAME}
66 | EOF
67 |
68 | #### To spoof whole entry in /proc/self/[maps|smaps] statically ####
69 | cat </dev/null
70 | ## Mode 1 ##
71 | TARGET_PID=$(/system/bin/ps -ef | grep "PROCESS_NAME" | head -n1 | awk '{print $2}')
72 | PATHNAME_TO_SEARCH="/system/etc/hosts"
73 | TARGET_INO=$(cat /proc/${TARGET_PID}/maps | grep -E "${PATHNAME_TO_SEARCH}" | head -n1 | awk '{print $5}')
74 | if [ ! -z ${TARGET_INO} ]; then
75 | MODE=1
76 | SPOOFED_PATHNAME="empty"
77 | SPOOFED_INO=0
78 | SPOOFED_DEV=0
79 | SPOOFED_PGOFF=0
80 | SPOOFED_PROT="---p"
81 | ${SUSFS_BIN} add_sus_maps_statically ${MODE} ${TARGET_INO} ${SPOOFED_PATHNAME} ${SPOOFED_INO} ${SPOOFED_DEV} ${SPOOFED_PGOFF} ${SPOOFED_PROT}
82 | fi
83 |
84 | ## Mode 2, entry is not isolated, previous ino of target ino and next ino of target ino == (target ino +- 1) ##
85 | TARGET_PID=$(/system/bin/ps -ef | grep "PROCESS_NAME" | head -n1 | awk '{print $2}')
86 | PATHNAME_TO_SEARCH="/system/etc/hosts"
87 | TARGET_INO=$(cat /proc/${TARGET_PID}/maps | grep -E "${PATHNAME_TO_SEARCH}" | head -n1 | awk '{print $5}')
88 | if [ ! -z ${TARGET_INO} ]; then
89 | MODE=2
90 | TARGET_ADDR_SIZE=4096
91 | TARGET_PGOFF=0
92 | TARGET_PROT="r--p"
93 | SPOOFED_PATHNAME=/syste/etc/my_hosts
94 | SPOOFED_INO="default"
95 | SPOOFED_DEV="default"
96 | SPOOFED_PGOFF="default"
97 | SPOOFED_PROT="default"
98 | IS_ISOLATED_ENTRY=0
99 | ${SUSFS_BIN} add_sus_maps_statically ${MODE} ${TARGET_INO} ${TARGET_ADDR_SIZE} ${TARGET_PGOFF} ${TARGET_PROT} ${SPOOFED_PATHNAME} ${SPOOFED_INO} ${SPOOFED_DEV} ${SPOOFED_PGOFF} ${SPOOFED_PROT} ${IS_ISOLATED_ENTRY}
100 | fi
101 |
102 | ## Mode 2, but entry is isolated, not consecutive ##
103 | TARGET_PID=$(/system/bin/ps -ef | grep "PROCESS_NAME" | head -n1 | awk '{print $2}')
104 | PATHNAME_TO_SEARCH="/system/etc/hosts"
105 | TARGET_INO=$(cat /proc/${TARGET_PID}/maps | grep -E "${PATHNAME_TO_SEARCH}" | head -n1 | awk '{print $5}')
106 | if [ ! -z ${TARGET_INO} ]; then
107 | MODE=2
108 | TARGET_PGOFF=0
109 | TARGET_PROT="r--p"
110 | SPOOFED_PATHNAME=/syste/etc/my_hosts
111 | SPOOFED_INO=0
112 | SPOOFED_DEV=0
113 | SPOOFED_PGOFF=0
114 | SPOOFED_PROT="---p"
115 | IS_ISOLATED_ENTRY=1
116 | ${SUSFS_BIN} add_sus_maps_statically ${MODE} ${TARGET_INO} ${TARGET_PGOFF} ${TARGET_PROT} ${SPOOFED_PATHNAME} ${SPOOFED_INO} ${SPOOFED_DEV} ${SPOOFED_PGOFF} ${SPOOFED_PROT} ${IS_ISOLATED_ENTRY}
117 | fi
118 |
119 | ## Mode 3, current entry ino is 0, compare with prev_target_ino and next_target_ino ##
120 | ## Note: when prev_target_ino or next_target_ino is 0, it will not be compared, if both are not zero, both will be compared ##
121 | MODE=3
122 | PREV_TARGET_INO=0
123 | PREV_TARGET_INO=30
124 | SPOOFED_PATHNAME="empty"
125 | SPOOFED_INO=0
126 | SPOOFED_DEV=0
127 | SPOOFED_PGOFF=0
128 | SPOOFED_PROT="---p"
129 | ${SUSFS_BIN} add_sus_maps_statically ${MODE} ${TARGET_INO} ${TARGET_PGOFF} ${TARGET_PROT} ${SPOOFED_PATHNAME} ${SPOOFED_INO} ${SPOOFED_DEV} ${SPOOFED_PGOFF} ${SPOOFED_PROT} ${IS_ISOLATED_ENTRY}
130 |
131 | ## Mode 4, all entries match with [is_file,target_addr_size,target_prot,target_pgoff,target_dev] will be spoofed with user defined entry ##
132 | MODE=4
133 | IS_FILE=1
134 | TARGET_DEV=6
135 | TARGET_PGOFF=$(echo $((0x2000000)))
136 | TARGET_PROT="rw-p"
137 | TARGET_ADDR_SIZE=$(echo $((0x2000000)))
138 | SPOOFED_PATHNAME="empty"
139 | SPOOFED_INO=0
140 | SPOOFED_DEV=0
141 | SPOOFED_PGOFF=0
142 | SPOOFED_PROT="---p"
143 | ${SUSFS_BIN} add_sus_maps_statically ${MODE} ${IS_FILE} ${TARGET_DEV} ${TARGET_PGOFF} ${TARGET_PROT} ${TARGET_ADDR_SIZE} ${SPOOFED_PATHNAME} ${SPOOFED_INO} ${SPOOFED_DEV} ${SPOOFED_PGOFF} ${SPOOFED_PROT}
144 | EOF
145 |
146 | #### To spoof the link path in /proc/self/fd/ ####
147 | cat </dev/null
148 | ${SUSFS_BIN} add_sus_proc_fd_link "/dev/binder" "/dev/null"
149 | EOF
150 |
151 | #### To prevent a memfd from being created by all process ####
152 | cat </dev/null
153 | ${SUSFS_BIN} add_sus_memfd "memfd:/jit-cache"
154 | EOF
155 |
--------------------------------------------------------------------------------
/ksu_module_susfs/service.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 |
3 | MODDIR=${0%/*}
4 |
5 | SUSFS_BIN=/data/adb/ksu/bin/ksu_susfs
6 |
7 |
--------------------------------------------------------------------------------
/ksu_module_susfs/tools/ksu_susfs_arm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/backslashxx/susfs4ksu/30e66dc3a5c65954de865afd8f44682866887544/ksu_module_susfs/tools/ksu_susfs_arm
--------------------------------------------------------------------------------
/ksu_module_susfs/tools/ksu_susfs_arm64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/backslashxx/susfs4ksu/30e66dc3a5c65954de865afd8f44682866887544/ksu_module_susfs/tools/ksu_susfs_arm64
--------------------------------------------------------------------------------
/ksu_module_susfs/uninstall.sh:
--------------------------------------------------------------------------------
1 | rm -f /data/adb/ksu/bin/ksu_susfs
2 |
3 |
--------------------------------------------------------------------------------
/ksu_susfs/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LOCAL_MODULE := ksu_susfs
6 | LOCAL_SRC_FILES := main.c
7 | LOCAL_LDFLAGS := -static
8 |
9 | include $(BUILD_EXECUTABLE)
10 |
--------------------------------------------------------------------------------
/ksu_susfs/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := arm64-v8a armeabi-v7a x86 x86_64
2 | APP_PLATFORM := latest
3 |
--------------------------------------------------------------------------------
/ksu_susfs/jni/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | /******************
16 | ** Define Macro **
17 | ******************/
18 | #define TAG "ksu_susfs"
19 | #define KERNEL_SU_OPTION 0xDEADBEEF
20 |
21 | #define CMD_SUSFS_ADD_SUS_PATH 0x55555
22 | #define CMD_SUSFS_ADD_SUS_MOUNT 0x55556
23 | #define CMD_SUSFS_ADD_SUS_KSTAT 0x55558
24 | #define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55559
25 | #define CMD_SUSFS_ADD_TRY_UMOUNT 0x5555a
26 | #define CMD_SUSFS_SET_UNAME 0x5555b
27 | #define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x5555c
28 | #define CMD_SUSFS_ENABLE_LOG 0x5555d
29 | #define CMD_SUSFS_ADD_SUS_MAPS_STATICALLY 0x5555e
30 | #define CMD_SUSFS_ADD_SUS_PROC_FD_LINK 0x5555f
31 | #define CMD_SUSFS_ADD_SUS_MAPS 0x55560
32 | #define CMD_SUSFS_UPDATE_SUS_MAPS 0x55561
33 | #define CMD_SUSFS_ADD_SUS_MEMFD 0x55562
34 |
35 | #define SUSFS_MAX_LEN_PATHNAME 256
36 | #define SUSFS_MAX_LEN_MFD_NAME 248
37 | #define SUSFS_MAX_LEN_MOUNT_TYPE_NAME 32
38 |
39 | #ifndef TIME_HAVE_NANOSEC
40 | #define TIME_HAVE_NANOSEC
41 | #endif
42 |
43 | #ifndef __NEW_UTS_LEN
44 | #define __NEW_UTS_LEN 64
45 | #endif
46 |
47 | /* VM flags from linux kernel */
48 | #define VM_NONE 0x00000000
49 | #define VM_READ 0x00000001 /* currently active flags */
50 | #define VM_WRITE 0x00000002
51 | #define VM_EXEC 0x00000004
52 | #define VM_SHARED 0x00000008
53 | /* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */
54 | #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */
55 | #define VM_MAYWRITE 0x00000020
56 | #define VM_MAYEXEC 0x00000040
57 | #define VM_MAYSHARE 0x00000080
58 |
59 | #define log(fmt, msg...) printf(TAG ":" fmt, ##msg);
60 |
61 | /*******************
62 | ** Define Struct **
63 | *******************/
64 | struct st_susfs_sus_path {
65 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
66 | unsigned long target_ino;
67 | };
68 |
69 | struct st_susfs_sus_mount {
70 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
71 | };
72 |
73 | struct st_susfs_sus_kstat {
74 | unsigned long target_ino; // the ino after bind mounted or overlayed
75 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
76 | char spoofed_pathname[SUSFS_MAX_LEN_PATHNAME];
77 | unsigned long spoofed_ino;
78 | unsigned long spoofed_dev;
79 | unsigned int spoofed_nlink;
80 | long spoofed_atime_tv_sec;
81 | long spoofed_mtime_tv_sec;
82 | long spoofed_ctime_tv_sec;
83 | #ifdef TIME_HAVE_NANOSEC
84 | long spoofed_atime_tv_nsec;
85 | long spoofed_mtime_tv_nsec;
86 | long spoofed_ctime_tv_nsec;
87 | #endif
88 | };
89 |
90 | struct st_susfs_sus_maps {
91 | bool is_statically;
92 | int compare_mode;
93 | bool is_isolated_entry;
94 | bool is_file;
95 | unsigned long prev_target_ino;
96 | unsigned long next_target_ino;
97 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
98 | unsigned long target_ino;
99 | unsigned long target_dev;
100 | unsigned long long target_pgoff;
101 | unsigned long target_prot;
102 | unsigned long target_addr_size;
103 | char spoofed_pathname[SUSFS_MAX_LEN_PATHNAME];
104 | unsigned long spoofed_ino;
105 | unsigned long spoofed_dev;
106 | unsigned long long spoofed_pgoff;
107 | unsigned long spoofed_prot;
108 | bool need_to_spoof_pathname;
109 | bool need_to_spoof_ino;
110 | bool need_to_spoof_dev;
111 | bool need_to_spoof_pgoff;
112 | bool need_to_spoof_prot;
113 | };
114 |
115 | struct st_susfs_try_umount {
116 | char target_pathname[SUSFS_MAX_LEN_PATHNAME];
117 | int mnt_mode;
118 | };
119 |
120 | struct st_susfs_sus_proc_fd_link {
121 | char target_link_name[SUSFS_MAX_LEN_PATHNAME];
122 | char spoofed_link_name[SUSFS_MAX_LEN_PATHNAME];
123 | };
124 |
125 | struct st_susfs_sus_memfd {
126 | char target_pathname[SUSFS_MAX_LEN_MFD_NAME];
127 | };
128 |
129 | struct st_susfs_uname {
130 | char sysname[__NEW_UTS_LEN+1];
131 | char nodename[__NEW_UTS_LEN+1];
132 | char release[__NEW_UTS_LEN+1];
133 | char version[__NEW_UTS_LEN+1];
134 | char machine[__NEW_UTS_LEN+1];
135 | };
136 |
137 | /**********************
138 | ** Define Functions **
139 | **********************/
140 | void pre_check() {
141 | if (getuid() != 0) {
142 | log("[-] Must run as root\n");
143 | exit(1);
144 | }
145 | }
146 |
147 | int isNumeric(char* str) {
148 | // Check if the string is empty
149 | if (str[0] == '\0') {
150 | return 0;
151 | }
152 |
153 | // Check each character in the string
154 | for (int i = 0; str[i] != '\0'; i++) {
155 | // If any character is not a digit, return false
156 | if (!isdigit(str[i])) {
157 | return 0;
158 | }
159 | }
160 |
161 | // All characters are digits, return true
162 | return 1;
163 | }
164 |
165 | int get_file_stat(char *pathname, struct stat* sb) {
166 | if (stat(pathname, sb) != 0) {
167 | return 1;
168 | }
169 | return 0;
170 | }
171 |
172 | void copy_stat_to_sus_kstat(struct st_susfs_sus_kstat* info, struct stat* sb) {
173 | info->spoofed_ino = sb->st_ino;
174 | info->spoofed_dev = sb->st_dev;
175 | info->spoofed_nlink = sb->st_nlink;
176 | info->spoofed_atime_tv_sec = sb->st_atime;
177 | info->spoofed_mtime_tv_sec = sb->st_mtime;
178 | info->spoofed_ctime_tv_sec = sb->st_ctime;
179 | info->spoofed_atime_tv_nsec = sb->st_atime_nsec;
180 | info->spoofed_mtime_tv_nsec = sb->st_mtime_nsec;
181 | info->spoofed_ctime_tv_nsec = sb->st_ctime_nsec;
182 | }
183 |
184 | void copy_stat_to_sus_maps(struct st_susfs_sus_maps* info, struct stat* sb) {
185 | info->spoofed_ino = sb->st_ino;
186 | info->spoofed_dev = sb->st_dev;
187 | }
188 |
189 | int create_file(const char* filename) {
190 | FILE* file = fopen(filename, "w+");
191 |
192 | if (file != NULL) {
193 | printf("File '%s' created successfully.\n", filename);
194 | fclose(file);
195 | } else {
196 | printf("Failed to create file '%s'.\n", filename);
197 | return 1;
198 | }
199 | return 0;
200 | }
201 |
202 | static void print_help(void) {
203 | log(" usage: %s [CMD options]\n", TAG);
204 | log(" :\n");
205 | log(" add_sus_path \n");
206 | log(" |--> Added path will be hidden from several syscalls\n");
207 | log("\n");
208 | log(" add_sus_mount \n");
209 | log(" |--> Added mounted path will be hidden from /proc/self/[mounts|mountinfo|mountstats]\n");
210 | log("\n");
211 | log(" add_sus_kstat_statically \\\n");
212 | log(" \n");
213 | log(" |--> Add the desired path for spoofing user defined [ino,dev,atime,atime_nsec,mtime,mtime_nsec,ctime,ctime_nsec]\n");
214 | log(" |--> Use 'stat' tool to find the format of ino -> %%i, dev -> %%d, nlink -> %%h atime -> %%X, mtime -> %%Y, ctime -> %%Z\n");
215 | log(" |--> e.g., %s add_sus_kstat_statically '/system/addon.d' '1234' '1234' '2'\\\n", TAG);
216 | log(" '1712592355' '0' '1712592355' '0' '1712592355' '0' '1712592355' '0'\n");
217 | log(" |--> Or pass 'default' to use its original value:\n");
218 | log(" |--> e.g., %s add_sus_kstat_statically '/system/addon.d' 'default' 'default' 'default'\\\n", TAG);
219 | log(" '1712592355' 'default' '1712592355' 'default' '1712592355' 'default'\n");
220 | log("\n");
221 | log(" add_sus_kstat \n");
222 | log(" |--> Add the desired path before it gets bind mounted or overlayed, this is used for storing original stat info in kernel memory\n");
223 | log(" |--> This command must be completed with later after the added path is bind mounted or overlayed\n");
224 | log("\n");
225 | log(" update_sus_kstat \n");
226 | log(" |--> Add the desired path you have added before via to complete the kstat spoofing procedure\n");
227 | log("\n");
228 | log(" add_sus_maps \n");
229 | log(" |--> Matched ino in /proc/self/[maps|smaps] will be spoofed for the user defined [ino] and [dev] ONLY!\n");
230 | log("\n");
231 | log(" update_sus_maps \n");
232 | log(" |--> Add the desired path you have added before via to complete the [ino] and [dev] spoofing in maps\n");
233 | log("\n");
234 | log(" add_sus_maps_statically \n");
235 | log(" |--> compare_mode: 1 => target_ino is 'non-zero', all entries match target_ino will be spoofed with user defined entry\n");
236 | log(" |--> \n");
237 | log(" |--> \n");
238 | log(" |--> \n");
239 | log(" |--> \n");
240 | log(" |--> \n");
241 | log(" |--> \n");
242 | log(" |--> compare_mode: 2 => target_ino is 'non-zero', all entries match [target_ino,target_addr_size,target_pgoff,target_prot,is_isolated_entry] will be spoofed with user defined entry\n");
243 | log(" |--> : in decimal\n");
244 | log(" |--> : in decimal\n");
245 | log(" |--> : in decimal\n");
246 | log(" |--> : in string, must be length of 4, and include only characters 'rwxps-', e.g.: 'r--s'\n");
247 | log(" |--> : in string, can be passed as 'default' or 'empty'\n");
248 | log(" |--> : in decimal, can be passed as 'default'\n");
249 | log(" |--> : in decimal, can be passed as 'default'\n");
250 | log(" |--> : in decimal, can be passed as 'default'\n");
251 | log(" |--> : in string, must be length of 4, and include only characters 'rwxps-', e.g.: 'r--s', can be passed as 'default'\n");
252 | log(" |--> : 0 -> not isolated entry, 1 -> isolated entry\n");
253 | log(" |--> compare_mode: 3 => target_ino is 'zero', all entries match [prev_target_ino,next_target_ino] will be spoofed with user defined entry\n");
254 | log(" |--> Note: one of and must be > 0, if both are > 0, then both will be compared\n");
255 | log(" |--> : in decimal, must be >= 0, if 0, then it will not be compared\n");
256 | log(" |--> : in decimal, must be >= 0, if 0, then it will not be compared\n");
257 | log(" |--> : in string, can be passed as 'default' or 'empty'\n");
258 | log(" |--> : in decimal, can be passed as 'default'\n");
259 | log(" |--> : in decimal, can be passed as 'default'\n");
260 | log(" |--> : in decimal, can be passed as 'default'\n");
261 | log(" |--> : in string, must be length of 4, and include only characters 'rwxps-', e.g.: 'r--s', can be passed as 'default'\n");
262 | log(" |--> compare_mode: 4 => all entries match [is_file,target_addr_size,target_prot,target_pgoff,target_dev] will be spoofed with user defined entry\n");
263 | log(" |--> : '0' or '1', 0 -> NOT a file, 0 -> IS a file\n");
264 | log(" |--> : in decimal, must be >= 0\n");
265 | log(" |--> : in decimal, must be >= 0\n");
266 | log(" |--> : in string, must be length of 4, and include only characters 'rwxps-', e.g.: 'r--s', can be passed as 'default'\n");
267 | log(" |--> : in decimal, must be > 0\n");
268 | log(" |--> : in string, can be passed as 'default' or 'empty'\n");
269 | log(" |--> : in decimal, can be passed as 'default'\n");
270 | log(" |--> : in decimal, can be passed as 'default'\n");
271 | log(" |--> : in decimal, can be passed as 'default'\n");
272 | log(" |--> : in string, must be length of 4, and include only characters 'rwxps-', e.g.: 'r--s', can be passed as 'default'\n");
273 | log(" |--> 'default' args will be spoofed with the original value\n");
274 | log(" |--> 'empty' for will be spoofed with the empty pathname\n");
275 | log("\n");
276 | log(" add_try_umount \n");
277 | log(" |--> Added path will be umounted from KSU for all UIDs that are NOT su allowed, and profile template configured with umount\n");
278 | log(" |--> : 0 -> umount with no flags, 1 -> umount with MNT_DETACH\n");
279 | log(" |--> NOTE: susfs umount takes precedence of ksu umount\n");
280 | log("\n");
281 | log(" add_sus_proc_fd_link \n");
282 | log(" |--> Added symlinked path will be spoofed in /proc/self/fd/[xx] only\n");
283 | log(" |--> e.g., add_sus_proc_fd_link /dev/binder /dev/null\n");
284 | log(" |--> So if /proc/self/fd/10 is a symlink to /dev/binder, then it will be shown as /dev/null instead\n");
285 | log("\n");
286 | log(" add_sus_memfd \n");
287 | log(" |--> NOTE: This feature will be effective on all process\n");
288 | log(" |--> NOTE: Remeber to prepend 'memfd:' to \n");
289 | log(" |--> e.g., add_sus_memfd 'memfd:/jit-cache'\n");
290 | log("\n");
291 | log(" set_uname \n");
292 | log(" |--> Spoof uname for all processes, set string to 'default' to imply the function to use original string\n");
293 | log(" |--> e.g., set_uname 'default' 'default' '4.9.337-g3291538446b7' 'default' 'default' \n");
294 | log("\n");
295 | log(" enable_log <0|1>\n");
296 | log(" |--> 0: disable susfs log in kernel, 1: enable susfs log in kernel\n");
297 | log("\n");
298 | }
299 |
300 | /*******************
301 | ** Main Function **
302 | *******************/
303 | int main(int argc, char *argv[]) {
304 | int error = 1;
305 |
306 | pre_check();
307 | // add_sus_path
308 | if (argc == 3 && !strcmp(argv[1], "add_sus_path")) {
309 | struct st_susfs_sus_path info;
310 | struct stat sb;
311 |
312 | if (get_file_stat(argv[2], &sb)) {
313 | log("%s not found, skip adding its ino\n", info.target_pathname);
314 | return 1;
315 | }
316 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
317 | info.target_ino = sb.st_ino;
318 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_PATH, &info, NULL, &error);
319 | return error;
320 | // add_sus_mount
321 | } else if (argc == 3 && !strcmp(argv[1], "add_sus_mount")) {
322 | struct st_susfs_sus_mount info;
323 | struct stat sb;
324 |
325 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
326 | if (get_file_stat(argv[2], &sb)) {
327 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
328 | return 1;
329 | }
330 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_MOUNT, &info, NULL, &error);
331 | return error;
332 | // add_sus_kstat_statically
333 | } else if (argc == 12 && !strcmp(argv[1], "add_sus_kstat_statically")) {
334 | struct st_susfs_sus_kstat info;
335 | struct stat sb;
336 | char* endptr;
337 | unsigned long ino, dev, atime_nsec, mtime_nsec, ctime_nsec;
338 | unsigned int nlink;
339 | long atime, mtime, ctime;
340 |
341 | if (get_file_stat(argv[2], &sb)) {
342 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
343 | return 1;
344 | }
345 |
346 | if (strcmp(argv[3], "default")) {
347 | ino = strtoul(argv[3], &endptr, 10);
348 | if (*endptr != '\0') {
349 | print_help();
350 | return 1;
351 | }
352 | info.target_ino = sb.st_ino;
353 | sb.st_ino = ino;
354 | } else {
355 | info.target_ino = sb.st_ino;
356 | }
357 |
358 | if (strcmp(argv[4], "default")) {
359 | dev = strtoul(argv[4], &endptr, 10);
360 | if (*endptr != '\0') {
361 | print_help();
362 | return 1;
363 | }
364 | sb.st_dev = dev;
365 | }
366 | if (strcmp(argv[5], "default")) {
367 | nlink = strtoul(argv[5], &endptr, 10);
368 | if (*endptr != '\0') {
369 | print_help();
370 | return 1;
371 | }
372 | sb.st_nlink = nlink;
373 | }
374 | if (strcmp(argv[6], "default")) {
375 | atime = strtol(argv[6], &endptr, 10);
376 | if (*endptr != '\0') {
377 | print_help();
378 | return 1;
379 | }
380 | sb.st_atime = atime;
381 | }
382 | if (strcmp(argv[7], "default")) {
383 | atime_nsec = strtoul(argv[7], &endptr, 10);
384 | if (*endptr != '\0') {
385 | print_help();
386 | return 1;
387 | }
388 | sb.st_atimensec = atime_nsec;
389 | }
390 | if (strcmp(argv[8], "default")) {
391 | mtime = strtol(argv[8], &endptr, 10);
392 | if (*endptr != '\0') {
393 | print_help();
394 | return 1;
395 | }
396 | sb.st_mtime = mtime;
397 | }
398 | if (strcmp(argv[9], "default")) {
399 | mtime_nsec = strtoul(argv[9], &endptr, 10);
400 | if (*endptr != '\0') {
401 | print_help();
402 | return 1;
403 | }
404 | sb.st_mtimensec = mtime_nsec;
405 | }
406 | if (strcmp(argv[10], "default")) {
407 | ctime = strtol(argv[10], &endptr, 10);
408 | if (*endptr != '\0') {
409 | print_help();
410 | return 1;
411 | }
412 | sb.st_ctime = ctime;
413 | }
414 | if (strcmp(argv[11], "default")) {
415 | ctime_nsec = strtoul(argv[11], &endptr, 10);
416 | if (*endptr != '\0') {
417 | print_help();
418 | return 1;
419 | }
420 | sb.st_ctimensec = ctime_nsec;
421 | }
422 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
423 | copy_stat_to_sus_kstat(&info, &sb);
424 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY, &info, NULL, &error);
425 | return error;
426 | // add_sus_kstat
427 | } else if (argc == 3 && !strcmp(argv[1], "add_sus_kstat")) {
428 | struct st_susfs_sus_kstat info;
429 | struct stat sb;
430 |
431 | if (get_file_stat(argv[2], &sb)) {
432 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
433 | return 1;
434 | }
435 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
436 | info.target_ino = sb.st_ino;
437 | copy_stat_to_sus_kstat(&info, &sb);
438 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_KSTAT, &info, NULL, &error);
439 | return error;
440 | // update_sus_kstat
441 | } else if (argc == 3 && !strcmp(argv[1], "update_sus_kstat")) {
442 | struct st_susfs_sus_kstat info;
443 | struct stat sb;
444 |
445 | if (get_file_stat(argv[2], &sb)) {
446 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
447 | return 1;
448 | }
449 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
450 | info.target_ino = sb.st_ino;
451 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_UPDATE_SUS_KSTAT, &info, NULL, &error);
452 | return error;
453 | // add_sus_maps
454 | } else if (argc == 3 && !strcmp(argv[1], "add_sus_maps")) {
455 | struct st_susfs_sus_maps info;
456 | struct stat sb;
457 |
458 | if (get_file_stat(argv[2], &sb)) {
459 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
460 | return 1;
461 | }
462 | memset(&info, 0, sizeof(struct st_susfs_sus_maps));
463 | info.is_statically = false;
464 | info.target_ino = sb.st_ino;
465 | copy_stat_to_sus_maps(&info, &sb);
466 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
467 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_MAPS, &info, NULL, &error);
468 | return error;
469 | // update_sus_maps
470 | } else if (argc == 3 && !strcmp(argv[1], "update_sus_maps")) {
471 | struct st_susfs_sus_maps info;
472 | struct stat sb = {0};
473 |
474 | if (get_file_stat(argv[2], &sb)) {
475 | log("[-] Failed to get stat from path: '%s'\n", argv[2]);
476 | return 1;
477 | }
478 | info.target_ino = sb.st_ino;
479 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
480 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_UPDATE_SUS_MAPS, &info, NULL, &error);
481 | return error;
482 | // add_sus_maps_statically
483 | } else if (argc > 3 && !strcmp(argv[1], "add_sus_maps_statically")) {
484 | struct st_susfs_sus_maps info;
485 | char* endptr;
486 |
487 | memset(&info, 0, sizeof(struct st_susfs_sus_maps));
488 | info.is_statically = true;
489 | info.compare_mode = strtoul(argv[2], &endptr, 10);
490 | if (*endptr != '\0' || info.compare_mode > 4 || info.compare_mode < 1) {
491 | log("[-] compare_mode must be [1|2|3|4]\n");
492 | return 1;
493 | }
494 | // compare_mode == 1
495 | if (info.compare_mode == 1 && argc == 9) {
496 | // target_ino
497 | info.target_ino = strtoul(argv[3], &endptr, 10);
498 | if (*endptr != '\0') {
499 | log("[-] target_ino must be a digit\n");
500 | return 1;
501 | }
502 | // spoofed_pathname
503 | if (strcmp(argv[4], "default")) {
504 | if (strcmp(argv[4], "empty")) {
505 | strncpy(info.spoofed_pathname, argv[4], SUSFS_MAX_LEN_PATHNAME-1);
506 | }
507 | info.need_to_spoof_pathname = true;
508 | }
509 | // spoofed_ino
510 | if (strcmp(argv[5], "default")) {
511 | info.spoofed_ino = strtoul(argv[5], &endptr, 10);
512 | if (*endptr != '\0') {
513 | log("[-] spoofed_ino must be a digit or 'default'\n");
514 | return 1;
515 | }
516 | info.need_to_spoof_ino = true;
517 | }
518 | // spoofed_dev
519 | if (strcmp(argv[6], "default")) {
520 | info.spoofed_dev = strtoul(argv[6], &endptr, 10);
521 | if (*endptr != '\0') {
522 | log("[-] spoofed_dev must be a digit or 'default'\n");
523 | return 1;
524 | }
525 | info.need_to_spoof_dev = true;
526 | }
527 | // spoofed_pgoff
528 | if (strcmp(argv[7], "default")) {
529 | info.spoofed_pgoff = strtoul(argv[7], &endptr, 10);
530 | if (*endptr != '\0') {
531 | log("[-] spoofed_pgoff must be a digit or 'default'\n");
532 | return 1;
533 | }
534 | info.need_to_spoof_pgoff = true;
535 | }
536 | // spoofed_prot
537 | if (strcmp(argv[8], "default")) {
538 | if (strlen(argv[8]) != 4 ||
539 | ((argv[8][0] != 'r' && argv[8][0] != '-') ||
540 | (argv[8][1] != 'w' && argv[8][1] != '-') ||
541 | (argv[8][2] != 'x' && argv[8][2] != '-') ||
542 | (argv[8][3] != 'p' && argv[8][3] != 's')))
543 | {
544 | log("[-] spoofed_prot must match length of 'rwxp', and include only 'rwxps-' charaters\n");
545 | return 1;
546 | }
547 | if (argv[8][0] == 'r') info.spoofed_prot |= VM_READ;
548 | if (argv[8][1] == 'w') info.spoofed_prot |= VM_WRITE;
549 | if (argv[8][2] == 'x') info.spoofed_prot |= VM_EXEC;
550 | if (argv[8][3] == 's') info.spoofed_prot |= VM_MAYSHARE;
551 | info.need_to_spoof_prot = true;
552 | }
553 | // compare_mode == 2
554 | } else if (info.compare_mode == 2 && argc == 13) {
555 | // target_ino
556 | info.target_ino = strtoul(argv[3], &endptr, 10);
557 | if (*endptr != '\0') {
558 | print_help();
559 | return 1;
560 | }
561 | // target_addr_size
562 | info.target_addr_size = strtoul(argv[4], &endptr, 10);
563 | if (*endptr != '\0') {
564 | print_help();
565 | return 1;
566 | }
567 | // target_pgoff
568 | info.target_pgoff = strtoul(argv[5], &endptr, 10);
569 | if (*endptr != '\0') {
570 | print_help();
571 | return 1;
572 | }
573 | // target_prot
574 | if (strlen(argv[6]) != 4 ||
575 | ((argv[6][0] != 'r' && argv[6][0] != '-') ||
576 | (argv[6][1] != 'w' && argv[6][1] != '-') ||
577 | (argv[6][2] != 'x' && argv[6][2] != '-') ||
578 | (argv[6][3] != 'p' && argv[6][3] != 's')))
579 | {
580 | print_help();
581 | return 1;
582 | }
583 | if (argv[6][0] == 'r') info.target_prot |= VM_READ;
584 | if (argv[6][1] == 'w') info.target_prot |= VM_WRITE;
585 | if (argv[6][2] == 'x') info.target_prot |= VM_EXEC;
586 | if (argv[6][3] == 's') info.target_prot |= VM_MAYSHARE;
587 | // spoofed_pathname
588 | if (strcmp(argv[7], "default")) {
589 | if (strcmp(argv[7], "empty")) {
590 | strncpy(info.spoofed_pathname, argv[7], SUSFS_MAX_LEN_PATHNAME-1);
591 | }
592 | info.need_to_spoof_pathname = true;
593 | }
594 | // spoofed_ino
595 | if (strcmp(argv[8], "default")) {
596 | info.spoofed_ino = strtoul(argv[8], &endptr, 10);
597 | if (*endptr != '\0') {
598 | print_help();
599 | return 1;
600 | }
601 | info.need_to_spoof_ino = true;
602 | }
603 | // spoofed_dev
604 | if (strcmp(argv[9], "default")) {
605 | info.spoofed_dev = strtoul(argv[9], &endptr, 10);
606 | if (*endptr != '\0') {
607 | print_help();
608 | return 1;
609 | }
610 | info.need_to_spoof_dev = true;
611 | }
612 | // spoofed_pgoff
613 | if (strcmp(argv[10], "default")) {
614 | info.spoofed_pgoff = strtoul(argv[10], &endptr, 10);
615 | if (*endptr != '\0') {
616 | print_help();
617 | return 1;
618 | }
619 | info.need_to_spoof_pgoff = true;
620 | }
621 | // spoofed_prot
622 | if (strcmp(argv[11], "default")) {
623 | if (strlen(argv[11]) != 4 ||
624 | ((argv[11][0] != 'r' && argv[11][0] != '-') ||
625 | (argv[11][1] != 'w' && argv[11][1] != '-') ||
626 | (argv[11][2] != 'x' && argv[11][2] != '-') ||
627 | (argv[11][3] != 'p' && argv[11][3] != 's')))
628 | {
629 | print_help();
630 | return 1;
631 | }
632 | if (argv[11][0] == 'r') info.spoofed_prot |= VM_READ;
633 | if (argv[11][1] == 'w') info.spoofed_prot |= VM_WRITE;
634 | if (argv[11][2] == 'x') info.spoofed_prot |= VM_EXEC;
635 | if (argv[11][3] == 's') info.spoofed_prot |= VM_MAYSHARE;
636 | info.need_to_spoof_prot = true;
637 | }
638 | // is_isolated_entry
639 | if (strcmp(argv[12], "0") && strcmp(argv[12], "1")) {
640 | print_help();
641 | return 1;
642 | }
643 | if (!strcmp(argv[12], "0")) {
644 | info.is_isolated_entry = false;
645 | } else {
646 | info.is_isolated_entry = true;
647 | }
648 | // compare_mode == 3
649 | } else if (info.compare_mode == 3 && argc == 10) {
650 | // prev_target_ino
651 | info.prev_target_ino = strtoul(argv[3], &endptr, 10);
652 | if (*endptr != '\0') {
653 | print_help();
654 | return 1;
655 | }
656 | // next_target_ino
657 | info.next_target_ino = strtoul(argv[4], &endptr, 10);
658 | if (*endptr != '\0') {
659 | print_help();
660 | return 1;
661 | }
662 | if (info.prev_target_ino == 0 && info.next_target_ino == 0) {
663 | log("[-] prev_target_ino and next_target_ino cannot be 0 at the same time, one of them must be > 0\n");
664 | return 1;
665 | }
666 | // spoofed_pathname
667 | if (strcmp(argv[5], "default")) {
668 | if (strcmp(argv[5], "empty")) {
669 | strncpy(info.spoofed_pathname, argv[5], SUSFS_MAX_LEN_PATHNAME-1);
670 | }
671 | info.need_to_spoof_pathname = true;
672 | }
673 | // spoofed_ino
674 | if (strcmp(argv[6], "default")) {
675 | info.spoofed_ino = strtoul(argv[6], &endptr, 10);
676 | if (*endptr != '\0') {
677 | print_help();
678 | return 1;
679 | }
680 | info.need_to_spoof_ino = true;
681 | }
682 | // spoofed_dev
683 | if (strcmp(argv[7], "default")) {
684 | info.spoofed_dev = strtoul(argv[7], &endptr, 10);
685 | if (*endptr != '\0') {
686 | print_help();
687 | return 1;
688 | }
689 | info.need_to_spoof_dev = true;
690 | }
691 | // spoofed_pgoff
692 | if (strcmp(argv[8], "default")) {
693 | info.spoofed_pgoff = strtoul(argv[8], &endptr, 10);
694 | if (*endptr != '\0') {
695 | print_help();
696 | return 1;
697 | }
698 | info.need_to_spoof_pgoff = true;
699 | }
700 | // spoofed_prot
701 | if (strcmp(argv[9], "default")) {
702 | if (strlen(argv[9]) != 4 ||
703 | ((argv[9][0] != 'r' && argv[9][0] != '-') ||
704 | (argv[9][1] != 'w' && argv[9][1] != '-') ||
705 | (argv[9][2] != 'x' && argv[9][2] != '-') ||
706 | (argv[9][3] != 'p' && argv[9][3] != 's')))
707 | {
708 | print_help();
709 | return 1;
710 | }
711 | if (argv[9][0] == 'r') info.spoofed_prot |= VM_READ;
712 | if (argv[9][1] == 'w') info.spoofed_prot |= VM_WRITE;
713 | if (argv[9][2] == 'x') info.spoofed_prot |= VM_EXEC;
714 | if (argv[9][3] == 's') info.spoofed_prot |= VM_MAYSHARE;
715 | info.need_to_spoof_prot = true;
716 | }
717 | } else if (info.compare_mode == 4 && argc == 13) {
718 | // is_file
719 | if (strcmp(argv[3], "0") && strcmp(argv[3], "1")) {
720 | print_help();
721 | return 1;
722 | }
723 | info.is_file = strtoul(argv[3], &endptr, 10);
724 | // target_dev
725 | info.target_dev = strtoul(argv[4], &endptr, 10);
726 | if (*endptr != '\0') {
727 | print_help();
728 | return 1;
729 | }
730 | // target_pgoff
731 | info.target_pgoff = strtoul(argv[5], &endptr, 10);
732 | if (*endptr != '\0') {
733 | print_help();
734 | return 1;
735 | }
736 | // target_prot
737 | if (strlen(argv[6]) != 4 ||
738 | ((argv[6][0] != 'r' && argv[6][0] != '-') ||
739 | (argv[6][1] != 'w' && argv[6][1] != '-') ||
740 | (argv[6][2] != 'x' && argv[6][2] != '-') ||
741 | (argv[6][3] != 'p' && argv[6][3] != 's')))
742 | {
743 | print_help();
744 | return 1;
745 | }
746 | if (argv[6][0] == 'r') info.target_prot |= VM_READ;
747 | if (argv[6][1] == 'w') info.target_prot |= VM_WRITE;
748 | if (argv[6][2] == 'x') info.target_prot |= VM_EXEC;
749 | if (argv[6][3] == 's') info.target_prot |= VM_MAYSHARE;
750 | // target_addr_size
751 | info.target_addr_size = strtoul(argv[7], &endptr, 10);
752 | if (*endptr != '\0') {
753 | print_help();
754 | return 1;
755 | }
756 | // spoofed_pathname
757 | if (strcmp(argv[8], "default")) {
758 | if (strcmp(argv[8], "empty")) {
759 | strncpy(info.spoofed_pathname, argv[8], SUSFS_MAX_LEN_PATHNAME-1);
760 | }
761 | info.need_to_spoof_pathname = true;
762 | }
763 | // spoofed_ino
764 | if (strcmp(argv[9], "default")) {
765 | info.spoofed_ino = strtoul(argv[9], &endptr, 10);
766 | if (*endptr != '\0') {
767 | print_help();
768 | return 1;
769 | }
770 | info.need_to_spoof_ino = true;
771 | }
772 | // spoofed_dev
773 | if (strcmp(argv[10], "default")) {
774 | info.spoofed_dev = strtoul(argv[10], &endptr, 10);
775 | if (*endptr != '\0') {
776 | print_help();
777 | return 1;
778 | }
779 | info.need_to_spoof_dev = true;
780 | }
781 | // spoofed_pgoff
782 | if (strcmp(argv[11], "default")) {
783 | info.spoofed_pgoff = strtoul(argv[11], &endptr, 10);
784 | if (*endptr != '\0') {
785 | print_help();
786 | return 1;
787 | }
788 | info.need_to_spoof_pgoff = true;
789 | }
790 | // spoofed_prot
791 | if (strcmp(argv[12], "default")) {
792 | if (strlen(argv[12]) != 4 ||
793 | ((argv[12][0] != 'r' && argv[12][0] != '-') ||
794 | (argv[12][1] != 'w' && argv[12][1] != '-') ||
795 | (argv[12][2] != 'x' && argv[12][2] != '-') ||
796 | (argv[12][3] != 'p' && argv[12][3] != 's')))
797 | {
798 | print_help();
799 | return 1;
800 | }
801 | if (argv[12][0] == 'r') info.spoofed_prot |= VM_READ;
802 | if (argv[12][1] == 'w') info.spoofed_prot |= VM_WRITE;
803 | if (argv[12][2] == 'x') info.spoofed_prot |= VM_EXEC;
804 | if (argv[12][3] == 's') info.spoofed_prot |= VM_MAYSHARE;
805 | info.need_to_spoof_prot = true;
806 | }
807 | } else {
808 | print_help();
809 | return 1;
810 | }
811 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_MAPS_STATICALLY, &info, NULL, &error);
812 | return error;
813 | // add_try_umount
814 | } else if (argc == 4 && !strcmp(argv[1], "add_try_umount")) {
815 | struct st_susfs_try_umount info;
816 | char* endptr;
817 | char abs_path[PATH_MAX], *p_abs_path;
818 |
819 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
820 | p_abs_path = realpath(info.target_pathname, abs_path);
821 | if (p_abs_path == NULL) {
822 | perror("realpath");
823 | return 1;
824 | }
825 | if (!strcmp(p_abs_path, "/system") ||
826 | !strcmp(p_abs_path, "/vendor") ||
827 | !strcmp(p_abs_path, "/product") ||
828 | !strcmp(p_abs_path, "/data/adb/modules") ||
829 | !strcmp(p_abs_path, "/debug_ramdisk") ||
830 | !strcmp(p_abs_path, "/sbin")) {
831 | printf("[-] %s cannot be added to try_umount, because it will be umounted by ksu lastly\n", p_abs_path);
832 | return 1;
833 | }
834 | if (strcmp(argv[3], "0") && strcmp(argv[3], "1")) {
835 | print_help();
836 | return 1;
837 | }
838 | info.mnt_mode = strtol(argv[3], &endptr, 10);
839 | if (*endptr != '\0') {
840 | print_help();
841 | return 1;
842 | }
843 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_TRY_UMOUNT, &info, NULL, &error);
844 | return error;
845 | // add_sus_proc_fd_link
846 | } else if (argc == 4 && !strcmp(argv[1], "add_sus_proc_fd_link")) {
847 | struct st_susfs_sus_proc_fd_link info;
848 |
849 | strncpy(info.target_link_name, argv[2], SUSFS_MAX_LEN_PATHNAME-1);
850 | strncpy(info.spoofed_link_name, argv[3], SUSFS_MAX_LEN_PATHNAME-1);
851 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_PROC_FD_LINK, &info, NULL, &error);
852 | return error;
853 | // add_sus_memfd
854 | } else if (argc == 3 && !strcmp(argv[1], "add_sus_memfd")) {
855 | struct st_susfs_sus_memfd info;
856 |
857 | memset(&info, 0, sizeof(struct st_susfs_sus_memfd));
858 | strncpy(info.target_pathname, argv[2], SUSFS_MAX_LEN_MFD_NAME-1);
859 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ADD_SUS_MEMFD, &info, NULL, &error);
860 | return error;
861 | // set_uname
862 | } else if (argc == 7 && !strcmp(argv[1], "set_uname")) {
863 | struct st_susfs_uname info;
864 |
865 | strncpy(info.sysname, argv[2], __NEW_UTS_LEN);
866 | strncpy(info.nodename, argv[3], __NEW_UTS_LEN);
867 | strncpy(info.release, argv[4], __NEW_UTS_LEN);
868 | strncpy(info.version, argv[5], __NEW_UTS_LEN);
869 | strncpy(info.machine, argv[6], __NEW_UTS_LEN);
870 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_SET_UNAME, &info, NULL, &error);
871 | return error;
872 | // enable_log
873 | } else if (argc == 3 && !strcmp(argv[1], "enable_log")) {
874 | if (strcmp(argv[2], "0") && strcmp(argv[2], "1")) {
875 | print_help();
876 | return 1;
877 | }
878 | prctl(KERNEL_SU_OPTION, CMD_SUSFS_ENABLE_LOG, atoi(argv[2]), NULL, &error);
879 | return error;
880 | } else {
881 | print_help();
882 | }
883 | out:
884 | return 0;
885 | }
886 |
--------------------------------------------------------------------------------