├── .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 | --------------------------------------------------------------------------------