#29027: file_move_safe error with SELinux
------------------------------------------------+-------------------------
Reporter: bhargu | Owner: nobody
Type: Bug | Status: new
Component: File uploads/storage | Version: 1.11
Severity: Normal | Keywords: selinux
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------------+-------------------------
PermissionError on upload of large files (large enough to not use the in-
memory file class) when SELinux is in enforce mode.
The error happens after the file is copied to the destination folder. As
seen in the trace below, when copystat is called from file_move_safe,
shutil tries to set attributes with setxattr. But this is failing when
SELinux is enabled. I noticed on temporarily disabling SELinux that the
files which are successfully uploaded now have a context of 'httpd_tmp_t'
as opposed to the context of 'httpd_sys_rw_content_t' which the directory
is configured with.
So, when SELinux is enabled, setxattr is failing when the context of the
file is 'httpd_sys_rw_content_t'.
{{{
Traceback (most recent call last):
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/handlers/base.py", line 249, in _legacy_get_response
response = self._get_response(request)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args,
**callback_kwargs)
File "/home/portal/venv/lib/python3.6/site-
packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/portal/project/assignments/views/views.py", line 270, in
edit_answer
instance.answerfile_set.create(file=upload, file_type=file)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/fields/related_descriptors.py", line 653, in
create
return super(RelatedManager, self.db_manager(db)).create(**kwargs)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/query.py", line 394, in create
obj.save(force_insert=True, using=self.db)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/base.py", line 808, in save
force_update=force_update, update_fields=update_fields)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/base.py", line 838, in save_base
updated = self._save_table(raw, cls, force_insert, force_update,
using, update_fields)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/base.py", line 924, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk,
raw)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/base.py", line 963, in _do_insert
using=using, raw=raw)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/query.py", line 1076, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/sql/compiler.py", line 1111, in execute_sql
for sql, params in self.as_sql():
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/sql/compiler.py", line 1064, in as_sql
for obj in self.query.objs
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/sql/compiler.py", line 1064, in <listcomp>
for obj in self.query.objs
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/sql/compiler.py", line 1063, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in
fields]
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/sql/compiler.py", line 1013, in pre_save_val
return field.pre_save(obj, add=True)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/fields/files.py", line 296, in pre_save
file.save(file.name, file.file, save=False)
File "/home/portal/venv/lib/python3.6/site-
packages/django/db/models/fields/files.py", line 94, in save
self.name = self.storage.save(name, content,
max_length=self.field.max_length)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/files/storage.py", line 54, in save
return self._save(name, content)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/files/storage.py", line 338, in _save
file_move_safe(content.temporary_file_path(), full_path)
File "/home/portal/venv/lib/python3.6/site-
packages/django/core/files/move.py", line 76, in file_move_safe
copystat(old_file_name, new_file_name)
File "/usr/lib64/python3.6/shutil.py", line 225, in copystat
_copyxattr(src, dst, follow_symlinks=follow)
File "/usr/lib64/python3.6/shutil.py", line 165, in _copyxattr
os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
PermissionError: [Errno 13] Permission denied:
'/home/portal/project/media/submission/8/69_424/10465_fxjc_1_27691_uljy_1_46853.png'
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29027>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.a282eb68d4e8370c75c35fc4857c749c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.