umask

(PHP 4, PHP 5, PHP 7, PHP 8)

umask更改当前 umask

描述

umask(?int $mask = null): int

umask() 将 PHP 的 umask 设置为 mask & 0777 并返回旧的 umask。当 PHP 用作服务器模块时,umask 在每个请求完成后恢复。

参数

mask

新的 umask。

返回值

如果 masknullumask() 仅返回当前的 umask,否则返回旧的 umask。

变更日志

版本 描述
8.0.0 mask 现在可以为空。

范例

示例 #1 umask() 示例

<?php
$old
= umask(0);
chmod("/path/some_dir/some_file.txt", 0755);
umask($old);

// 检查
if ($old != umask()) {
die(
'更改回 umask 时发生错误');
}
?>

注释

注意:

避免在多线程 Web 服务器中使用此函数。最好在创建文件后使用 chmod() 更改文件权限。使用 umask() 可能会导致同时运行的脚本和 Web 服务器本身的行为出现意外,因为它们都使用相同的 umask。

添加注释

用户贡献的注释 14 个注释

librodot at ciberpiula dot net
15 年前
我认为理解 umask 的最佳方式是说 umask 用于撤销权限,而不是设置权限。

umask 设置在创建文件或目录时必须从系统默认值中删除哪些权限。

例如,掩码 0022 表示您不希望组和其他人修改文件。

默认 0666 rw-.rw-.rw-
umask 0022 ---.-w-.-w-
最终 0644 rw-.r--.r--

这意味着从现在起,任何文件都将具有 0644 权限。

重要的是要了解 umask 撤销、删除系统默认值中的权限,因此它无法授予系统默认值没有的权限。在上面的示例中,使用 666 系统默认值,您无法使用 umask 创建具有执行权限的文件。如果您想授予更多权限,请使用 chmod。

请注意,系统默认权限与 PHP 无关(它们取决于服务器配置)。PHP 具有一个默认的 umask,它在系统默认基本权限之后应用。并且文件和目录有不同的系统默认基本权限。

通常,文件的系统默认权限为 666,目录的系统默认权限为 0777。通常,PHP 默认 umask 为 0022
sean at awesomeplay dot com
17 年前
"最好在创建文件后使用 chmod() 更改文件权限."

PHP 团队中普遍缺乏安全知识再次暴露出来。您*始终*希望文件以正确的权限创建。让我说明为什么

(a) 您以读取权限创建新文件
(b) 一个攻击脚本打开文件
(c) 您使用 chmod 将文件更改为删除读取权限
(d) 您将敏感数据写入文件

现在,您可能认为攻击脚本在您使用 chmod 更改权限之前打开文件的可能性很低。你说得对。但低概率永远不够低 - 您希望为零。

在创建需要提升权限的文件时,您始终需要以正确的权限创建文件,并使用 O_EXCL 设置创建文件。如果您没有进行排他性创建,您将遇到以下情况

(a) 攻击者创建文件,使其对所有人可写
(b) 您以受限权限打开文件,但由于它已存在,因此仅打开文件,权限保持不变
(c) 您将敏感数据写入不安全的 文件

检测后一种情况是可能的,但这需要一些工作。您必须检查文件的拥有者和组是否与脚本的拥有者和组匹配(即 posix_geteuid(),而不是 myuid()),并检查权限 - 如果这些权限中的任何一个不正确,则该文件是不安全的 - 您可以尝试 unlink() 它并重试,当然,还要记录警告。

在创建文件后使用 chmod() 更改文件权限的唯一合理或安全时间是当您想授予额外的权限而不是删除权限时。例如,将 umask 设置为 0077,然后使用 chmod 更改之后创建的文件的权限是完全安全的。

在 PHP 中进行真正安全的编程本来就很困难,而文档中这样的建议只会让事情变得更糟。记住,孩子们,任何适用于 C 或 UNIX 世界的安全内容都 100% 适用于 PHP。作为 PHP 程序员,您能为自己做的最好的事情就是学习和理解安全的 C 和 UNIX 编程技术。
匿名
18 年前
使用 (cmask - umask) 是计算新掩码的错误方法

0022 - 0700 = 0656 错误
0700 & ~0022 = 0700 正确

正确的 php 代码
<?php
$rmask
= ($cmask & ~$umask);
?>
neon at neonjs dot com
13 年前
如果您不明白为什么您需要“避免在多线程 Web 服务器中使用此函数”

这是因为此函数在进程级别更改 umask,而不是仅针对 PHP 或当前脚本更改。如果在运行 PHP 脚本的进程中有多个同时运行的线程,则更改将同时应用于所有这些线程,因此这对于多线程使用来说是不安全的。

我理解,如果您使用 PHP 模块和 Apache 的 prefork MPM(不是多线程的),那么您至少不会遇到这样的竞争条件问题。但是,仍然值得注意的是,umask 设置(如果未重新设置)将在该进程的整个生命周期内持续存在,即使该进程被重新使用以服务未来的 PHP 或非 PHP 请求也是如此。
Richard Snell
8 年前
重要的是要注意,mask 参数将接受八进制以外的值,这会导致意外结果。

设置 umask(22) 预计会通过应用 0022 的掩码将默认权限为 0666 的文件减少到 0644,但由于参数以十进制形式提供,因此它将被静默地转换为八进制,实际上应用 0026 的掩码,导致最终的文件权限为 0642。

类似地,umask 返回的值为十进制格式。如果您使用 umask(0022) 正确应用掩码,然后使用 umask() 查询新设置,它将返回 18 的值(0022 八进制为 18 十进制)。

简而言之,在应用权限时,最好用零填充提供的值以创建八进制值(22 变成 0022),如果您想分析返回值,请记住将其转换为八进制以便于解释。
malcolm.murphy
8 年前
"mask & 0777" 的澄清

手册中关于“umask() 将 PHP 的 umask 设置为 mask & 0777 [...]” 的评论只是暗示该方法只影响文件权限,而不影响诸如 setuid、setgid 或粘性位之类的特殊模式。奇怪的是,PHP 实际上并没有执行位运算本身,而是假设它将由同名的系统调用完成。在某些系统(如 OS X)上,umask 会有效地将 umask 设置为 mask & 07777,但多余的位不适用于随后的 PHP 调用(如 mkdir())。Linux 的 umask 使用 0777。它的手册条目有一个类似于 PHP 中的评论,但有一个括号内的语句有助于解释它的含义

"umask() 设置调用进程的文件模式创建掩码(umask)为 mask & 0777(即,仅使用 mask 的文件权限位)[...]"

尽管与 $mask & 0777 的外观相似,但使用运算 $mask & ~0777 通过反转掩码来确定权限是无关紧要的。后一个运算反而将 $mask 截断为前九个低位(即,三个最右边的八进制数字[并且要注意,八进制表示法的前导零本身不是一个数字])。它不会改变其余的位。

例如,以下所有调用具有相同的效果:umask(0022)、umask(07022)、umask(261650)(0777022 的十进制值)和 umask(0b111000010010)(07022 的二进制表示法)。
jphansen at uga dot edu
16 年前
在大多数 UNIX 环境中,在 /home/user/.profile 或 /etc/profile 中定义的推荐的默认文件 umask 为 022(chmod: 644)。在可信系统中,它为 002。在应用更宽松的设置时请谨慎。
webmaster at iacomputing dot co dot uk
13 年前
您可以使用 umask 来解决出现在多个 PHP 版本中的 PHP 会话错误。

<?php
umask
(0022);
session_start();
?>

这将防止创建具有不充分权限的会话。
bishop
13 年前
"最好在创建文件后使用 chmod() 更改文件权限."

如果您认真对待这条建议,请考虑设置您的 umask 使文件对您的用户私有,然后使用 chmod 打开它们。

<?php
// 文件将创建为 -rw-------
umask(0077);

// 创建一个文件,例如 fopen()

// 授予访问权限:-rw-r--r--
chmod('/path/to/file', 0644);
?>

只要合理,默认设置为关闭并在需要时打开(如上所示),而不是默认设置为打开并在需要时关闭。上面的方法仍然存在竞争条件,但竞争条件将拒绝适当的访问而不是授予不适当的访问。
ahmad dot mayahi at gmail dot com
7 年前
简单地说,umask 表示新文件/目录的默认权限。

<?php
umask
(022);
?>

这设置了用户、组和其他人各自的默认权限。

• 0 - 读取、写入和执行
• 1 - 读取和写入
• 2 - 读取和执行
• 3 - 只读
• 4 - 写入和执行
• 5 - 仅写入
• 6 - 仅执行
• 7 - 无权限
andi<at>splitbrain.org
19 年前
要玩转 umask 和权限,请使用这段小片段

<?
$umask = 0012;
$perm = 0777;
printf("umask: %04o perm: %04o result: %04o\n",
$umask,$perm,$perm & (0777 - $umask));
?>
maulwuff at gmx dot de
16 年前
umask 从标准掩码 777 中减去给定的值。
图形视图可以更好地展示这一点。

标准
rwxrwxrwx = 777
使用 umask 002 将获得
rwxrwxr-x = 775
或使用 umask 077 将获得
rwx------ = 700

等等。
sam at totallydigital dot co dot nz
21 年前
第一个评论可能没有完全清楚说明您的 umask 和权限是怎么回事。

传递给命令的权限首先与当前 umask 的_反_进行按位 AND 运算,然后应用于文件。

例如,umask = 0011 且 permission = 0775
0011 的反 = 0766

0775 AND 0766
= 111.111.101 AND 111.110.110
= 111.110.100
= 0764
ShaD@TW
18 年前
请注意,目录和文件有时具有不同的结果。

<?php
umask
(0670); //- 设置 umask
$handle = fopen('file', 'w'); //- 0006
mkdir("/path/dir"); //- 0107
?>

计算结果
<?php
$umask
= 0670;
umask($umask);
//- 如果您要创建一个新目录,则 $permission = 0777;
//- 如果您要创建一个新文件,则 $permission = 0666.
printf( "result: %04o", $permission & ( 0777 - $umask) );
?>

顺便说一句,正如手册中所述,umask() 的形式为“int umask ([int mask])”,因此如果您想打印/回显任何 umask,请不要忘记将其从 DEC(因为它返回一个“int”)转换为 OCT。

<?php
$umask
= umask(); //- 返回当前 umask,它是一个“int”
$umask = decoct($umask); //- 现在,$umask 是一个“string”
echo $umask;
?>

不要忘记参数也是一个“int”。

<?php
umask
(777); //- 错误!即使您可能在某些操作系统中使用“umask 777”。
umask(0777); //- 正确
?>

如果有任何错误,请更正我的陈述。
To Top