susfs.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. #include <linux/version.h>
  2. #include <linux/cred.h>
  3. #include <linux/fs.h>
  4. #include <linux/slab.h>
  5. #include <linux/seq_file.h>
  6. #include <linux/printk.h>
  7. #include <linux/namei.h>
  8. #include <linux/list.h>
  9. #include <linux/init_task.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/stat.h>
  12. #include <linux/uaccess.h>
  13. #include <linux/version.h>
  14. #include <linux/fdtable.h>
  15. #include <linux/statfs.h>
  16. #include <linux/susfs.h>
  17. #include "mount.h"
  18. static spinlock_t susfs_spin_lock;
  19. extern bool susfs_is_current_ksu_domain(void);
  20. #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
  21. extern void ksu_try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid);
  22. #endif
  23. #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
  24. bool susfs_is_log_enabled __read_mostly = true;
  25. #define SUSFS_LOGI(fmt, ...) if (susfs_is_log_enabled) pr_info("susfs:[%u][%d][%s] " fmt, current_uid().val, current->pid, __func__, ##__VA_ARGS__)
  26. #define SUSFS_LOGE(fmt, ...) if (susfs_is_log_enabled) pr_err("susfs:[%u][%d][%s]" fmt, current_uid().val, current->pid, __func__, ##__VA_ARGS__)
  27. #else
  28. #define SUSFS_LOGI(fmt, ...)
  29. #define SUSFS_LOGE(fmt, ...)
  30. #endif
  31. /* sus_path */
  32. #ifdef CONFIG_KSU_SUSFS_SUS_PATH
  33. static DEFINE_HASHTABLE(SUS_PATH_HLIST, 10);
  34. static int susfs_update_sus_path_inode(char *target_pathname) {
  35. struct path p;
  36. struct inode *inode = NULL;
  37. const char *dev_type;
  38. if (kern_path(target_pathname, LOOKUP_FOLLOW, &p)) {
  39. SUSFS_LOGE("Failed opening file '%s'\n", target_pathname);
  40. return 1;
  41. }
  42. // - We don't allow paths of which filesystem type is "tmpfs" or "fuse".
  43. // For tmpfs, because its starting inode->i_ino will begin with 1 again,
  44. // so it will cause wrong comparison in function susfs_sus_ino_for_filldir64()
  45. // For fuse, which is almost storage related, sus_path should not handle any paths of
  46. // which filesystem is "fuse" as well, since app can write to "fuse" and lookup files via
  47. // like binder / system API (you can see the uid is changed to 1000)/
  48. // - so sus_path should be applied only on read-only filesystem like "erofs" or "f2fs", but not "tmpfs" or "fuse",
  49. // people may rely on HMA for /data isolation instead.
  50. dev_type = p.mnt->mnt_sb->s_type->name;
  51. if (!strcmp(dev_type, "tmpfs") ||
  52. !strcmp(dev_type, "fuse")) {
  53. SUSFS_LOGE("target_pathname: '%s' cannot be added since its filesystem type is '%s'\n",
  54. target_pathname, dev_type);
  55. path_put(&p);
  56. return 1;
  57. }
  58. inode = d_inode(p.dentry);
  59. if (!inode) {
  60. SUSFS_LOGE("inode is NULL\n");
  61. path_put(&p);
  62. return 1;
  63. }
  64. if (!(inode->i_state & INODE_STATE_SUS_PATH)) {
  65. spin_lock(&inode->i_lock);
  66. inode->i_state |= INODE_STATE_SUS_PATH;
  67. spin_unlock(&inode->i_lock);
  68. }
  69. path_put(&p);
  70. return 0;
  71. }
  72. int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info) {
  73. struct st_susfs_sus_path info;
  74. struct st_susfs_sus_path_hlist *new_entry, *tmp_entry;
  75. struct hlist_node *tmp_node;
  76. int bkt;
  77. bool update_hlist = false;
  78. if (copy_from_user(&info, user_info, sizeof(info))) {
  79. SUSFS_LOGE("failed copying from userspace\n");
  80. return 1;
  81. }
  82. spin_lock(&susfs_spin_lock);
  83. hash_for_each_safe(SUS_PATH_HLIST, bkt, tmp_node, tmp_entry, node) {
  84. if (!strcmp(tmp_entry->target_pathname, info.target_pathname)) {
  85. hash_del(&tmp_entry->node);
  86. kfree(tmp_entry);
  87. update_hlist = true;
  88. break;
  89. }
  90. }
  91. spin_unlock(&susfs_spin_lock);
  92. new_entry = kmalloc(sizeof(struct st_susfs_sus_path_hlist), GFP_KERNEL);
  93. if (!new_entry) {
  94. SUSFS_LOGE("no enough memory\n");
  95. return 1;
  96. }
  97. new_entry->target_ino = info.target_ino;
  98. strncpy(new_entry->target_pathname, info.target_pathname, SUSFS_MAX_LEN_PATHNAME-1);
  99. if (susfs_update_sus_path_inode(new_entry->target_pathname)) {
  100. kfree(new_entry);
  101. return 1;
  102. }
  103. spin_lock(&susfs_spin_lock);
  104. hash_add(SUS_PATH_HLIST, &new_entry->node, info.target_ino);
  105. if (update_hlist) {
  106. SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' is successfully updated to SUS_PATH_HLIST\n",
  107. new_entry->target_ino, new_entry->target_pathname);
  108. } else {
  109. SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' is successfully added to SUS_PATH_HLIST\n",
  110. new_entry->target_ino, new_entry->target_pathname);
  111. }
  112. spin_unlock(&susfs_spin_lock);
  113. return 0;
  114. }
  115. int susfs_sus_ino_for_filldir64(unsigned long ino) {
  116. struct st_susfs_sus_path_hlist *entry;
  117. hash_for_each_possible(SUS_PATH_HLIST, entry, node, ino) {
  118. if (entry->target_ino == ino)
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. #endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
  124. /* sus_mount */
  125. #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
  126. static LIST_HEAD(LH_SUS_MOUNT);
  127. static void susfs_update_sus_mount_inode(char *target_pathname) {
  128. struct mount *mnt = NULL;
  129. struct path p;
  130. struct inode *inode = NULL;
  131. int err = 0;
  132. err = kern_path(target_pathname, LOOKUP_FOLLOW, &p);
  133. if (err) {
  134. SUSFS_LOGE("Failed opening file '%s'\n", target_pathname);
  135. return;
  136. }
  137. /* It is important to check if the mount has a legit peer group id, if so we cannot add them to sus_mount,
  138. * since there are chances that the mount is a legit mountpoint, and it can be misued by other susfs functions in future.
  139. * And by doing this it won't affect the sus_mount check as other susfs functions check by mnt->mnt_id
  140. * instead of INODE_STATE_SUS_MOUNT.
  141. */
  142. mnt = real_mount(p.mnt);
  143. if (mnt->mnt_group_id > 0 && // 0 means no peer group
  144. mnt->mnt_group_id < DEFAULT_SUS_MNT_GROUP_ID) {
  145. SUSFS_LOGE("skip setting SUS_MOUNT inode state for path '%s' since its source mount has a legit peer group id\n", target_pathname);
  146. return;
  147. }
  148. inode = d_inode(p.dentry);
  149. if (!inode) {
  150. path_put(&p);
  151. SUSFS_LOGE("inode is NULL\n");
  152. return;
  153. }
  154. if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
  155. spin_lock(&inode->i_lock);
  156. inode->i_state |= INODE_STATE_SUS_MOUNT;
  157. spin_unlock(&inode->i_lock);
  158. }
  159. path_put(&p);
  160. }
  161. int susfs_add_sus_mount(struct st_susfs_sus_mount* __user user_info) {
  162. struct st_susfs_sus_mount_list *cursor = NULL, *temp = NULL;
  163. struct st_susfs_sus_mount_list *new_list = NULL;
  164. struct st_susfs_sus_mount info;
  165. if (copy_from_user(&info, user_info, sizeof(info))) {
  166. SUSFS_LOGE("failed copying from userspace\n");
  167. return 1;
  168. }
  169. #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
  170. #ifdef CONFIG_MIPS
  171. info.target_dev = new_decode_dev(info.target_dev);
  172. #else
  173. info.target_dev = huge_decode_dev(info.target_dev);
  174. #endif /* CONFIG_MIPS */
  175. #else
  176. info.target_dev = old_decode_dev(info.target_dev);
  177. #endif /* defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) */
  178. list_for_each_entry_safe(cursor, temp, &LH_SUS_MOUNT, list) {
  179. if (unlikely(!strcmp(cursor->info.target_pathname, info.target_pathname))) {
  180. spin_lock(&susfs_spin_lock);
  181. memcpy(&cursor->info, &info, sizeof(info));
  182. susfs_update_sus_mount_inode(cursor->info.target_pathname);
  183. SUSFS_LOGI("target_pathname: '%s', target_dev: '%lu', is successfully updated to LH_SUS_MOUNT\n",
  184. cursor->info.target_pathname, cursor->info.target_dev);
  185. spin_unlock(&susfs_spin_lock);
  186. return 0;
  187. }
  188. }
  189. new_list = kmalloc(sizeof(struct st_susfs_sus_mount_list), GFP_KERNEL);
  190. if (!new_list) {
  191. SUSFS_LOGE("no enough memory\n");
  192. return 1;
  193. }
  194. memcpy(&new_list->info, &info, sizeof(info));
  195. susfs_update_sus_mount_inode(new_list->info.target_pathname);
  196. INIT_LIST_HEAD(&new_list->list);
  197. spin_lock(&susfs_spin_lock);
  198. list_add_tail(&new_list->list, &LH_SUS_MOUNT);
  199. SUSFS_LOGI("target_pathname: '%s', target_dev: '%lu', is successfully added to LH_SUS_MOUNT\n",
  200. new_list->info.target_pathname, new_list->info.target_dev);
  201. spin_unlock(&susfs_spin_lock);
  202. return 0;
  203. }
  204. #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
  205. int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target) {
  206. struct mount *mnt;
  207. struct inode *inode;
  208. mnt = real_mount(path_target->mnt);
  209. if (mnt->mnt_group_id > 0 && // 0 means no peer group
  210. mnt->mnt_group_id < DEFAULT_SUS_MNT_GROUP_ID) {
  211. SUSFS_LOGE("skip setting SUS_MOUNT inode state for path '%s' since its source mount has a legit peer group id\n", pathname);
  212. // return 0 here as we still want it to be added to try_umount list
  213. return 0;
  214. }
  215. inode = path_target->dentry->d_inode;
  216. if (!inode) return 1;
  217. if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
  218. spin_lock(&inode->i_lock);
  219. inode->i_state |= INODE_STATE_SUS_MOUNT;
  220. spin_unlock(&inode->i_lock);
  221. SUSFS_LOGI("set SUS_MOUNT inode state for source bind mount path '%s'\n", pathname);
  222. }
  223. return 0;
  224. }
  225. #endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
  226. #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
  227. void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname) {
  228. char *pathname = NULL;
  229. struct path path;
  230. struct inode *inode;
  231. pathname = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
  232. if (!pathname) {
  233. SUSFS_LOGE("no enough memory\n");
  234. return;
  235. }
  236. // Here we need to re-retrieve the struct path as we want the new struct path, not the old one
  237. if (strncpy_from_user(pathname, to_pathname, SUSFS_MAX_LEN_PATHNAME-1) < 0) {
  238. SUSFS_LOGE("strncpy_from_user()\n");
  239. goto out_free_pathname;
  240. return;
  241. }
  242. if ((!strncmp(pathname, "/data/adb/modules", 17) ||
  243. !strncmp(pathname, "/debug_ramdisk", 14) ||
  244. !strncmp(pathname, "/system", 7) ||
  245. !strncmp(pathname, "/system_ext", 11) ||
  246. !strncmp(pathname, "/vendor", 7) ||
  247. !strncmp(pathname, "/product", 8) ||
  248. !strncmp(pathname, "/odm", 4)) &&
  249. !kern_path(pathname, LOOKUP_FOLLOW, &path)) {
  250. goto set_inode_sus_mount;
  251. }
  252. goto out_free_pathname;
  253. set_inode_sus_mount:
  254. inode = path.dentry->d_inode;
  255. if (!inode) {
  256. goto out_path_put;
  257. return;
  258. }
  259. if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
  260. spin_lock(&inode->i_lock);
  261. inode->i_state |= INODE_STATE_SUS_MOUNT;
  262. spin_unlock(&inode->i_lock);
  263. SUSFS_LOGI("set SUS_MOUNT inode state for default KSU mount path '%s'\n", pathname);
  264. }
  265. out_path_put:
  266. path_put(&path);
  267. out_free_pathname:
  268. kfree(pathname);
  269. }
  270. #endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
  271. #endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
  272. /* sus_kstat */
  273. #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
  274. static DEFINE_HASHTABLE(SUS_KSTAT_HLIST, 10);
  275. static int susfs_update_sus_kstat_inode(char *target_pathname) {
  276. struct path p;
  277. struct inode *inode = NULL;
  278. int err = 0;
  279. err = kern_path(target_pathname, LOOKUP_FOLLOW, &p);
  280. if (err) {
  281. SUSFS_LOGE("Failed opening file '%s'\n", target_pathname);
  282. return 1;
  283. }
  284. // We don't allow path of which filesystem type is "tmpfs", because its inode->i_ino is starting from 1 again,
  285. // which will cause wrong comparison in function susfs_sus_ino_for_filldir64()
  286. if (strcmp(p.mnt->mnt_sb->s_type->name, "tmpfs") == 0) {
  287. SUSFS_LOGE("target_pathname: '%s' cannot be added since its filesystem is 'tmpfs'\n", target_pathname);
  288. path_put(&p);
  289. return 1;
  290. }
  291. inode = d_inode(p.dentry);
  292. if (!inode) {
  293. path_put(&p);
  294. SUSFS_LOGE("inode is NULL\n");
  295. return 1;
  296. }
  297. if (!(inode->i_state & INODE_STATE_SUS_KSTAT)) {
  298. spin_lock(&inode->i_lock);
  299. inode->i_state |= INODE_STATE_SUS_KSTAT;
  300. spin_unlock(&inode->i_lock);
  301. }
  302. path_put(&p);
  303. return 0;
  304. }
  305. int susfs_add_sus_kstat(struct st_susfs_sus_kstat* __user user_info) {
  306. struct st_susfs_sus_kstat info;
  307. struct st_susfs_sus_kstat_hlist *new_entry, *tmp_entry;
  308. struct hlist_node *tmp_node;
  309. int bkt;
  310. bool update_hlist = false;
  311. if (copy_from_user(&info, user_info, sizeof(info))) {
  312. SUSFS_LOGE("failed copying from userspace\n");
  313. return 1;
  314. }
  315. if (strlen(info.target_pathname) == 0) {
  316. SUSFS_LOGE("target_pathname is an empty string\n");
  317. return 1;
  318. }
  319. spin_lock(&susfs_spin_lock);
  320. hash_for_each_safe(SUS_KSTAT_HLIST, bkt, tmp_node, tmp_entry, node) {
  321. if (!strcmp(tmp_entry->info.target_pathname, info.target_pathname)) {
  322. hash_del(&tmp_entry->node);
  323. kfree(tmp_entry);
  324. update_hlist = true;
  325. break;
  326. }
  327. }
  328. spin_unlock(&susfs_spin_lock);
  329. new_entry = kmalloc(sizeof(struct st_susfs_sus_kstat_hlist), GFP_KERNEL);
  330. if (!new_entry) {
  331. SUSFS_LOGE("no enough memory\n");
  332. return 1;
  333. }
  334. #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
  335. #ifdef CONFIG_MIPS
  336. info.spoofed_dev = new_decode_dev(info.spoofed_dev);
  337. #else
  338. info.spoofed_dev = huge_decode_dev(info.spoofed_dev);
  339. #endif /* CONFIG_MIPS */
  340. #else
  341. info.spoofed_dev = old_decode_dev(info.spoofed_dev);
  342. #endif /* defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) */
  343. new_entry->target_ino = info.target_ino;
  344. memcpy(&new_entry->info, &info, sizeof(info));
  345. if (susfs_update_sus_kstat_inode(new_entry->info.target_pathname)) {
  346. kfree(new_entry);
  347. return 1;
  348. }
  349. spin_lock(&susfs_spin_lock);
  350. hash_add(SUS_KSTAT_HLIST, &new_entry->node, info.target_ino);
  351. #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
  352. if (update_hlist) {
  353. SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%llu', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully added to SUS_KSTAT_HLIST\n",
  354. new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
  355. new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
  356. new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
  357. new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
  358. new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
  359. new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
  360. } else {
  361. SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%llu', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully updated to SUS_KSTAT_HLIST\n",
  362. new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
  363. new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
  364. new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
  365. new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
  366. new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
  367. new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
  368. }
  369. #else
  370. if (update_hlist) {
  371. SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%u', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully added to SUS_KSTAT_HLIST\n",
  372. new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
  373. new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
  374. new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
  375. new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
  376. new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
  377. new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
  378. } else {
  379. SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%u', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully updated to SUS_KSTAT_HLIST\n",
  380. new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
  381. new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
  382. new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
  383. new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
  384. new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
  385. new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
  386. }
  387. #endif
  388. spin_unlock(&susfs_spin_lock);
  389. return 0;
  390. }
  391. int susfs_update_sus_kstat(struct st_susfs_sus_kstat* __user user_info) {
  392. struct st_susfs_sus_kstat info;
  393. struct st_susfs_sus_kstat_hlist *new_entry, *tmp_entry;
  394. struct hlist_node *tmp_node;
  395. int bkt;
  396. int err = 0;
  397. if (copy_from_user(&info, user_info, sizeof(info))) {
  398. SUSFS_LOGE("failed copying from userspace\n");
  399. return 1;
  400. }
  401. spin_lock(&susfs_spin_lock);
  402. hash_for_each_safe(SUS_KSTAT_HLIST, bkt, tmp_node, tmp_entry, node) {
  403. if (!strcmp(tmp_entry->info.target_pathname, info.target_pathname)) {
  404. if (susfs_update_sus_kstat_inode(tmp_entry->info.target_pathname)) {
  405. err = 1;
  406. goto out_spin_unlock;
  407. }
  408. new_entry = kmalloc(sizeof(struct st_susfs_sus_kstat_hlist), GFP_KERNEL);
  409. if (!new_entry) {
  410. SUSFS_LOGE("no enough memory\n");
  411. err = 1;
  412. goto out_spin_unlock;
  413. }
  414. memcpy(&new_entry->info, &tmp_entry->info, sizeof(tmp_entry->info));
  415. SUSFS_LOGI("updating target_ino from '%lu' to '%lu' for pathname: '%s' in SUS_KSTAT_HLIST\n",
  416. new_entry->info.target_ino, info.target_ino, info.target_pathname);
  417. new_entry->target_ino = info.target_ino;
  418. new_entry->info.target_ino = info.target_ino;
  419. if (info.spoofed_size > 0) {
  420. SUSFS_LOGI("updating spoofed_size from '%lld' to '%lld' for pathname: '%s' in SUS_KSTAT_HLIST\n",
  421. new_entry->info.spoofed_size, info.spoofed_size, info.target_pathname);
  422. new_entry->info.spoofed_size = info.spoofed_size;
  423. }
  424. if (info.spoofed_blocks > 0) {
  425. SUSFS_LOGI("updating spoofed_blocks from '%llu' to '%llu' for pathname: '%s' in SUS_KSTAT_HLIST\n",
  426. new_entry->info.spoofed_blocks, info.spoofed_blocks, info.target_pathname);
  427. new_entry->info.spoofed_blocks = info.spoofed_blocks;
  428. }
  429. hash_del(&tmp_entry->node);
  430. kfree(tmp_entry);
  431. hash_add(SUS_KSTAT_HLIST, &new_entry->node, info.target_ino);
  432. goto out_spin_unlock;
  433. }
  434. }
  435. out_spin_unlock:
  436. spin_unlock(&susfs_spin_lock);
  437. return err;
  438. }
  439. void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat) {
  440. struct st_susfs_sus_kstat_hlist *entry;
  441. hash_for_each_possible(SUS_KSTAT_HLIST, entry, node, ino) {
  442. if (entry->target_ino == ino) {
  443. stat->dev = entry->info.spoofed_dev;
  444. stat->ino = entry->info.spoofed_ino;
  445. stat->nlink = entry->info.spoofed_nlink;
  446. stat->size = entry->info.spoofed_size;
  447. stat->atime.tv_sec = entry->info.spoofed_atime_tv_sec;
  448. stat->atime.tv_nsec = entry->info.spoofed_atime_tv_nsec;
  449. stat->mtime.tv_sec = entry->info.spoofed_mtime_tv_sec;
  450. stat->mtime.tv_nsec = entry->info.spoofed_mtime_tv_nsec;
  451. stat->ctime.tv_sec = entry->info.spoofed_ctime_tv_sec;
  452. stat->ctime.tv_nsec = entry->info.spoofed_ctime_tv_nsec;
  453. stat->blocks = entry->info.spoofed_blocks;
  454. stat->blksize = entry->info.spoofed_blksize;
  455. return;
  456. }
  457. }
  458. }
  459. void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino) {
  460. struct st_susfs_sus_kstat_hlist *entry;
  461. hash_for_each_possible(SUS_KSTAT_HLIST, entry, node, ino) {
  462. if (entry->target_ino == ino) {
  463. *out_dev = entry->info.spoofed_dev;
  464. *out_ino = entry->info.spoofed_ino;
  465. return;
  466. }
  467. }
  468. }
  469. #endif // #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
  470. /* try_umount */
  471. #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
  472. static LIST_HEAD(LH_TRY_UMOUNT_PATH);
  473. int susfs_add_try_umount(struct st_susfs_try_umount* __user user_info) {
  474. struct st_susfs_try_umount_list *cursor = NULL, *temp = NULL;
  475. struct st_susfs_try_umount_list *new_list = NULL;
  476. struct st_susfs_try_umount info;
  477. if (copy_from_user(&info, user_info, sizeof(info))) {
  478. SUSFS_LOGE("failed copying from userspace\n");
  479. return 1;
  480. }
  481. list_for_each_entry_safe(cursor, temp, &LH_TRY_UMOUNT_PATH, list) {
  482. if (unlikely(!strcmp(info.target_pathname, cursor->info.target_pathname))) {
  483. SUSFS_LOGE("target_pathname: '%s' is already created in LH_TRY_UMOUNT_PATH\n", info.target_pathname);
  484. return 1;
  485. }
  486. }
  487. new_list = kmalloc(sizeof(struct st_susfs_try_umount_list), GFP_KERNEL);
  488. if (!new_list) {
  489. SUSFS_LOGE("no enough memory\n");
  490. return 1;
  491. }
  492. memcpy(&new_list->info, &info, sizeof(info));
  493. INIT_LIST_HEAD(&new_list->list);
  494. spin_lock(&susfs_spin_lock);
  495. list_add_tail(&new_list->list, &LH_TRY_UMOUNT_PATH);
  496. spin_unlock(&susfs_spin_lock);
  497. SUSFS_LOGI("target_pathname: '%s', mnt_mode: %d, is successfully added to LH_TRY_UMOUNT_PATH\n", new_list->info.target_pathname, new_list->info.mnt_mode);
  498. return 0;
  499. }
  500. void susfs_try_umount(uid_t target_uid) {
  501. struct st_susfs_try_umount_list *cursor = NULL;
  502. // We should umount in reversed order
  503. list_for_each_entry_reverse(cursor, &LH_TRY_UMOUNT_PATH, list) {
  504. if (cursor->info.mnt_mode == TRY_UMOUNT_DEFAULT) {
  505. ksu_try_umount(cursor->info.target_pathname, false, 0, target_uid);
  506. } else if (cursor->info.mnt_mode == TRY_UMOUNT_DETACH) {
  507. ksu_try_umount(cursor->info.target_pathname, false, MNT_DETACH, target_uid);
  508. } else {
  509. SUSFS_LOGE("failed umounting '%s' for uid: %d, mnt_mode '%d' not supported\n",
  510. cursor->info.target_pathname, target_uid, cursor->info.mnt_mode);
  511. }
  512. }
  513. }
  514. #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
  515. void susfs_auto_add_try_umount_for_bind_mount(struct path *path) {
  516. struct st_susfs_try_umount_list *cursor = NULL, *temp = NULL;
  517. struct st_susfs_try_umount_list *new_list = NULL;
  518. char *pathname = NULL, *dpath = NULL;
  519. #ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
  520. bool is_magic_mount_path = false;
  521. #endif
  522. #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
  523. if (path->dentry->d_inode->i_state & INODE_STATE_SUS_KSTAT) {
  524. SUSFS_LOGI("skip adding path to try_umount list as its inode is flagged INODE_STATE_SUS_KSTAT already\n");
  525. return;
  526. }
  527. #endif
  528. pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
  529. if (!pathname) {
  530. SUSFS_LOGE("no enough memory\n");
  531. return;
  532. }
  533. dpath = d_path(path, pathname, PAGE_SIZE);
  534. if (!dpath) {
  535. SUSFS_LOGE("dpath is NULL\n");
  536. goto out_free_pathname;
  537. }
  538. #ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
  539. if (strstr(dpath, MAGIC_MOUNT_WORKDIR)) {
  540. is_magic_mount_path = true;
  541. }
  542. #endif
  543. list_for_each_entry_safe(cursor, temp, &LH_TRY_UMOUNT_PATH, list) {
  544. #ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
  545. if (is_magic_mount_path && strstr(dpath, cursor->info.target_pathname)) {
  546. goto out_free_pathname;
  547. }
  548. #endif
  549. if (unlikely(!strcmp(dpath, cursor->info.target_pathname))) {
  550. SUSFS_LOGE("target_pathname: '%s', ino: %lu, is already created in LH_TRY_UMOUNT_PATH\n",
  551. dpath, path->dentry->d_inode->i_ino);
  552. goto out_free_pathname;
  553. }
  554. }
  555. new_list = kmalloc(sizeof(struct st_susfs_try_umount_list), GFP_KERNEL);
  556. if (!new_list) {
  557. SUSFS_LOGE("no enough memory\n");
  558. goto out_free_pathname;
  559. }
  560. #ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
  561. if (is_magic_mount_path) {
  562. strncpy(new_list->info.target_pathname, dpath + strlen(MAGIC_MOUNT_WORKDIR), SUSFS_MAX_LEN_PATHNAME-1);
  563. goto out_add_to_list;
  564. }
  565. #endif
  566. strncpy(new_list->info.target_pathname, dpath, SUSFS_MAX_LEN_PATHNAME-1);
  567. #ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
  568. out_add_to_list:
  569. #endif
  570. new_list->info.mnt_mode = TRY_UMOUNT_DETACH;
  571. INIT_LIST_HEAD(&new_list->list);
  572. spin_lock(&susfs_spin_lock);
  573. list_add_tail(&new_list->list, &LH_TRY_UMOUNT_PATH);
  574. spin_unlock(&susfs_spin_lock);
  575. SUSFS_LOGI("target_pathname: '%s', ino: %lu, mnt_mode: %d, is successfully added to LH_TRY_UMOUNT_PATH\n",
  576. new_list->info.target_pathname, path->dentry->d_inode->i_ino, new_list->info.mnt_mode);
  577. out_free_pathname:
  578. kfree(pathname);
  579. }
  580. #endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
  581. #endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
  582. /* spoof_uname */
  583. #ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
  584. static spinlock_t susfs_uname_spin_lock;
  585. static struct st_susfs_uname my_uname;
  586. static void susfs_my_uname_init(void) {
  587. memset(&my_uname, 0, sizeof(my_uname));
  588. }
  589. int susfs_set_uname(struct st_susfs_uname* __user user_info) {
  590. struct st_susfs_uname info;
  591. if (copy_from_user(&info, user_info, sizeof(struct st_susfs_uname))) {
  592. SUSFS_LOGE("failed copying from userspace.\n");
  593. return 1;
  594. }
  595. spin_lock(&susfs_uname_spin_lock);
  596. if (!strcmp(info.release, "default")) {
  597. strncpy(my_uname.release, utsname()->release, __NEW_UTS_LEN);
  598. } else {
  599. strncpy(my_uname.release, info.release, __NEW_UTS_LEN);
  600. }
  601. if (!strcmp(info.version, "default")) {
  602. strncpy(my_uname.version, utsname()->version, __NEW_UTS_LEN);
  603. } else {
  604. strncpy(my_uname.version, info.version, __NEW_UTS_LEN);
  605. }
  606. spin_unlock(&susfs_uname_spin_lock);
  607. SUSFS_LOGI("setting spoofed release: '%s', version: '%s'\n",
  608. my_uname.release, my_uname.version);
  609. return 0;
  610. }
  611. void susfs_spoof_uname(struct new_utsname* tmp) {
  612. if (unlikely(my_uname.release[0] == '\0' || spin_is_locked(&susfs_uname_spin_lock)))
  613. return;
  614. strncpy(tmp->release, my_uname.release, __NEW_UTS_LEN);
  615. strncpy(tmp->version, my_uname.version, __NEW_UTS_LEN);
  616. }
  617. #endif // #ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
  618. /* set_log */
  619. #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
  620. void susfs_set_log(bool enabled) {
  621. spin_lock(&susfs_spin_lock);
  622. susfs_is_log_enabled = enabled;
  623. spin_unlock(&susfs_spin_lock);
  624. if (susfs_is_log_enabled) {
  625. pr_info("susfs: enable logging to kernel");
  626. } else {
  627. pr_info("susfs: disable logging to kernel");
  628. }
  629. }
  630. #endif // #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
  631. /* spoof_cmdline_or_bootconfig */
  632. #ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
  633. static char *fake_cmdline_or_bootconfig = NULL;
  634. int susfs_set_cmdline_or_bootconfig(char* __user user_fake_cmdline_or_bootconfig) {
  635. int res;
  636. if (!fake_cmdline_or_bootconfig) {
  637. // 4096 is enough I guess
  638. fake_cmdline_or_bootconfig = kmalloc(SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE, GFP_KERNEL);
  639. if (!fake_cmdline_or_bootconfig) {
  640. SUSFS_LOGE("no enough memory\n");
  641. return -ENOMEM;
  642. }
  643. }
  644. spin_lock(&susfs_spin_lock);
  645. memset(fake_cmdline_or_bootconfig, 0, SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE);
  646. res = strncpy_from_user(fake_cmdline_or_bootconfig, user_fake_cmdline_or_bootconfig, SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE-1);
  647. spin_unlock(&susfs_spin_lock);
  648. if (res > 0) {
  649. #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
  650. SUSFS_LOGI("fake_cmdline_or_bootconfig is set, length of string: %lu\n", strlen(fake_cmdline_or_bootconfig));
  651. #else
  652. SUSFS_LOGI("fake_cmdline_or_bootconfig is set, length of string: %u\n", strlen(fake_cmdline_or_bootconfig));
  653. #endif
  654. return 0;
  655. }
  656. SUSFS_LOGI("failed setting fake_cmdline_or_bootconfig\n");
  657. return res;
  658. }
  659. int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m) {
  660. if (fake_cmdline_or_bootconfig != NULL) {
  661. seq_puts(m, fake_cmdline_or_bootconfig);
  662. return 0;
  663. }
  664. return 1;
  665. }
  666. #endif
  667. /* open_redirect */
  668. #ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
  669. static DEFINE_HASHTABLE(OPEN_REDIRECT_HLIST, 10);
  670. static int susfs_update_open_redirect_inode(struct st_susfs_open_redirect_hlist *new_entry) {
  671. struct path path_target;
  672. struct inode *inode_target;
  673. int err = 0;
  674. err = kern_path(new_entry->target_pathname, LOOKUP_FOLLOW, &path_target);
  675. if (err) {
  676. SUSFS_LOGE("Failed opening file '%s'\n", new_entry->target_pathname);
  677. return err;
  678. }
  679. inode_target = d_inode(path_target.dentry);
  680. if (!inode_target) {
  681. SUSFS_LOGE("inode_target is NULL\n");
  682. err = 1;
  683. goto out_path_put_target;
  684. }
  685. spin_lock(&inode_target->i_lock);
  686. inode_target->i_state |= INODE_STATE_OPEN_REDIRECT;
  687. spin_unlock(&inode_target->i_lock);
  688. out_path_put_target:
  689. path_put(&path_target);
  690. return err;
  691. }
  692. int susfs_add_open_redirect(struct st_susfs_open_redirect* __user user_info) {
  693. struct st_susfs_open_redirect info;
  694. struct st_susfs_open_redirect_hlist *new_entry, *tmp_entry;
  695. struct hlist_node *tmp_node;
  696. int bkt;
  697. bool update_hlist = false;
  698. if (copy_from_user(&info, user_info, sizeof(info))) {
  699. SUSFS_LOGE("failed copying from userspace\n");
  700. return 1;
  701. }
  702. spin_lock(&susfs_spin_lock);
  703. hash_for_each_safe(OPEN_REDIRECT_HLIST, bkt, tmp_node, tmp_entry, node) {
  704. if (!strcmp(tmp_entry->target_pathname, info.target_pathname)) {
  705. hash_del(&tmp_entry->node);
  706. kfree(tmp_entry);
  707. update_hlist = true;
  708. break;
  709. }
  710. }
  711. spin_unlock(&susfs_spin_lock);
  712. new_entry = kmalloc(sizeof(struct st_susfs_open_redirect_hlist), GFP_KERNEL);
  713. if (!new_entry) {
  714. SUSFS_LOGE("no enough memory\n");
  715. return 1;
  716. }
  717. new_entry->target_ino = info.target_ino;
  718. strncpy(new_entry->target_pathname, info.target_pathname, SUSFS_MAX_LEN_PATHNAME-1);
  719. strncpy(new_entry->redirected_pathname, info.redirected_pathname, SUSFS_MAX_LEN_PATHNAME-1);
  720. if (susfs_update_open_redirect_inode(new_entry)) {
  721. SUSFS_LOGE("failed adding path '%s' to OPEN_REDIRECT_HLIST\n", new_entry->target_pathname);
  722. kfree(new_entry);
  723. return 1;
  724. }
  725. spin_lock(&susfs_spin_lock);
  726. hash_add(OPEN_REDIRECT_HLIST, &new_entry->node, info.target_ino);
  727. if (update_hlist) {
  728. SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', redirected_pathname: '%s', is successfully updated to OPEN_REDIRECT_HLIST\n",
  729. new_entry->target_ino, new_entry->target_pathname, new_entry->redirected_pathname);
  730. } else {
  731. SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' redirected_pathname: '%s', is successfully added to OPEN_REDIRECT_HLIST\n",
  732. new_entry->target_ino, new_entry->target_pathname, new_entry->redirected_pathname);
  733. }
  734. spin_unlock(&susfs_spin_lock);
  735. return 0;
  736. }
  737. struct filename* susfs_get_redirected_path(unsigned long ino) {
  738. struct st_susfs_open_redirect_hlist *entry;
  739. hash_for_each_possible(OPEN_REDIRECT_HLIST, entry, node, ino) {
  740. if (entry->target_ino == ino) {
  741. SUSFS_LOGI("Redirect for ino: %lu\n", ino);
  742. return getname_kernel(entry->redirected_pathname);
  743. }
  744. }
  745. return ERR_PTR(-ENOENT);
  746. }
  747. #endif // #ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
  748. /* sus_su */
  749. #ifdef CONFIG_KSU_SUSFS_SUS_SU
  750. bool susfs_is_sus_su_hooks_enabled __read_mostly = false;
  751. static int susfs_sus_su_working_mode = 0;
  752. extern void ksu_susfs_enable_sus_su(void);
  753. extern void ksu_susfs_disable_sus_su(void);
  754. int susfs_get_sus_su_working_mode(void) {
  755. return susfs_sus_su_working_mode;
  756. }
  757. int susfs_sus_su(struct st_sus_su* __user user_info) {
  758. struct st_sus_su info;
  759. int last_working_mode = susfs_sus_su_working_mode;
  760. if (copy_from_user(&info, user_info, sizeof(struct st_sus_su))) {
  761. SUSFS_LOGE("failed copying from userspace\n");
  762. return 1;
  763. }
  764. if (info.mode == SUS_SU_WITH_HOOKS) {
  765. if (last_working_mode == SUS_SU_WITH_HOOKS) {
  766. SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_WITH_HOOKS);
  767. return 1;
  768. }
  769. if (last_working_mode != SUS_SU_DISABLED) {
  770. SUSFS_LOGE("please make sure the current sus_su mode is %d first\n", SUS_SU_DISABLED);
  771. return 2;
  772. }
  773. ksu_susfs_enable_sus_su();
  774. susfs_sus_su_working_mode = SUS_SU_WITH_HOOKS;
  775. susfs_is_sus_su_hooks_enabled = true;
  776. SUSFS_LOGI("core kprobe hooks for ksu are disabled!\n");
  777. SUSFS_LOGI("non-kprobe hook sus_su is enabled!\n");
  778. SUSFS_LOGI("sus_su mode: %d\n", SUS_SU_WITH_HOOKS);
  779. return 0;
  780. } else if (info.mode == SUS_SU_DISABLED) {
  781. if (last_working_mode == SUS_SU_DISABLED) {
  782. SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_DISABLED);
  783. return 1;
  784. }
  785. susfs_is_sus_su_hooks_enabled = false;
  786. ksu_susfs_disable_sus_su();
  787. susfs_sus_su_working_mode = SUS_SU_DISABLED;
  788. if (last_working_mode == SUS_SU_WITH_HOOKS) {
  789. SUSFS_LOGI("core kprobe hooks for ksu are enabled!\n");
  790. goto out;
  791. }
  792. out:
  793. if (copy_to_user(user_info, &info, sizeof(info)))
  794. SUSFS_LOGE("copy_to_user() failed\n");
  795. return 0;
  796. } else if (info.mode == SUS_SU_WITH_OVERLAY) {
  797. SUSFS_LOGE("sus_su mode %d is deprecated\n", SUS_SU_WITH_OVERLAY);
  798. return 1;
  799. }
  800. return 1;
  801. }
  802. #endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
  803. /* susfs_init */
  804. void susfs_init(void) {
  805. spin_lock_init(&susfs_spin_lock);
  806. #ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
  807. spin_lock_init(&susfs_uname_spin_lock);
  808. susfs_my_uname_init();
  809. #endif
  810. SUSFS_LOGI("susfs is initialized! version: " SUSFS_VERSION " \n");
  811. }
  812. /* No module exit is needed becuase it should never be a loadable kernel module */
  813. //void __init susfs_exit(void)