At work we offer a NAS service with one access method being cifs. The customers have a login and password that allows them to connect to the cifs share associated with their account and with the default mount options all files are owned by the cifs user which generally does not exist on the customers local system which is a whole other issue that I'm not going to go into. Many customers with linux systems mount the cifs share with a specified uid/gid for all the files so that their web server process can access the files on there or something to that end. This all sounds great and for the most part it works out pretty well aside from the fact that it's cifs which again is a whole other issue. The problem starts when many of these customers are disabling the unix extensions to cifs and manually specifying file_mode and dir_mode in their mount options. This is what the customer experiences: 1) Create file 2) List directory and see the mode of the file as say 660 (which also happens to be the value set in file_mode mount option) 3) They want to execute said file and with chmod go forth and do so 4) List the directory again and see the mode as they expect 770 or something similar. 5) After some time they try and execute the file only to get something similar to ./file: Permission Denied 6) At their dismay after an ls they see the file with the mode of 600 and open a support ticket. So what is going on here? Well the answer related to how the cifs driver deals with file attribute changes when the unix extensions are disabled. A quick poke through the 2.6.18 (centos 5.1) kernel source revealed what was going on. When the customer is runs chmod on the newly created file the VFS inode for that file is updated with the new attributes and the setattr handler in the cifs driver is called to update the underlaying filesystem. The handler is registered in struct inode_operations *i_op member of the vfs inode structure. That handler among many others is setup during initialization of the cifs driver. The action performed by the function cifs_setattr depend on of the unix extensions are enabled (currentl status can be viewd/set via /proc/fs/cifs/LinuxExtensionsEnabled). The cifs_setattr function silently changes or ignores certain values in the file attributes before actually sending the change to the cifs server. So why does the execute bit appear to work at all? Well because the cifs driver is silently ignoring the mode change before updating the server and doesn't update the local vfs inode we temporarily see the value that was set via chmod while the local inode exists in memory. Later on when the file is not accessed for a while that inode structure gets released from memory and when the file is accessed later on the local inode mode values get set via the file_mode/dir_mode values set at mount time. Fortunately this silent ignoring of the mode change has been fixed in more recent versions of the cifs driver included in kernel versions >=2.6.27. The new driver updates the local inode data structure to the value set by file_mode so the change is correctly ignored by both the cifs side and the vfs side. What can be done to resolve the issue? well for starters I'm not sure why we're telling customers to disable unix extensions in the first place which is something I do plan on looking into. So with the current configuration customers could either set their file_mode to something like 770 which isn't ideal. Alternatively they could write a super hack shell script to chmod the file they want to call right before it get executed so the vfs inode is in memory with the "correct" mode values. #!/bin/sh # SUPER HACK FILE=$1 [[ -f "$FILE" ]] || exit chmod +x "$FILE" || exit [[ -x "$FILE" ]] && exec "$FILE" Obviously this is a horrible work around and would have to exist on the local filesystem that can correctly store permissions values. So in conclusion don't expect file mode values to be anything different that what is set by the file_mode mount option when using cifs without the unix extensions enabled. Tags: code, work