普通用户创建的SYS V共享内存改属主为root后被非特权用户删除的原因咨询
为什么普通用户能删除属主为root的System V共享内存段?
我来帮你拆解这个反直觉的问题——你用普通用户身份创建了一段System V共享内存段,通过程序把它的UID和GID修改为0(也就是root用户),结果发现原来的普通用户居然还能删掉这个共享内存段,这背后的核心原因在于System V IPC对象的权限控制逻辑和文件系统不一样。
关键原因:创建者身份(cuid/cgid)优先于属主身份(uid/gid)
System V共享内存的权限由struct ipc_perm结构体控制,其中有几个核心字段:
uid/gid:共享内存段的属主、属组ID,这是你修改的字段cuid/cgid:共享内存段的创建者UID、GID,这个字段是不可被普通用户修改的(哪怕你调用shmctl(IPC_SET)也只能改uid、gid、mode,无法修改cuid/cgid)
哪怕你把uid改成root,只要cuid还是原来普通用户的UID,这个创建者用户就天然拥有对该共享内存段的完全控制权——包括查看、修改、删除操作,不受uid字段和权限位的限制。
结合你的代码分析
你的代码应该是通过shmctl的IPC_SET命令来修改共享内存的属主,补全逻辑后类似这样:
#include<stdio.h> #include<stdint.h> #include<sys/ipc.h> #include<sys/shm.h> int main(int argc, char *argv[]) { int ret = 0; int shmid = 0; key_t key = ftok(".", 'a'); // 示例key生成方式 struct shmid_ds shm_buf; // 普通用户身份创建共享内存段 shmid = shmget(key, 4096, IPC_CREAT | 0666); if (shmid == -1) { perror("shmget failed"); return 1; } // 获取当前共享内存属性 ret = shmctl(shmid, IPC_STAT, &shm_buf); if (ret == -1) { perror("shmctl IPC_STAT failed"); return 1; } // 修改属主为root shm_buf.shm_perm.uid = 0; shm_buf.shm_perm.gid = 0; // 应用修改 ret = shmctl(shmid, IPC_SET, &shm_buf); if (ret == -1) { perror("shmctl IPC_SET failed"); return 1; } printf("Shared memory owner changed to root\n"); return 0; }
这段代码修改了shm_perm.uid和shm_perm.gid,但没有也无法修改shm_perm.cuid和shm_perm.cgid,它们依然保留着创建该共享内存段的普通用户ID。所以这个普通用户依然能执行shmctl(shmid, IPC_RMID, NULL)来删除共享内存。
验证方式
你可以用ipcs -m -c命令查看共享内存段的创建者和属主信息,会看到类似这样的输出:
------ Shared Memory Creator/Owner Info -------- shmid creator creator owner owner uid gid uid gid 123456 1000 1000 0 0
这里的creator uid就是原来的普通用户ID,这就是为什么该用户能删除属主为root的共享内存段。
如何让普通用户无法删除?
如果想让原来的普通用户无法删除这个共享内存段,你需要:
- 用root用户直接创建共享内存段,此时
cuid和uid都是0,普通用户没有权限操作 - 注意:仅修改权限位(
shm_perm.mode)无法限制创建者,因为创建者天然拥有绕过权限位的操作权限,只有第一种方法能彻底限制。
内容的提问来源于stack exchange,提问作者rdssonawane
相关产品推荐
相关产品推荐

