Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
67232478
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
67232478
编写于
12月 14, 2016
作者:
M
Michal Privoznik
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
security_dac: Implement transaction APIs
Signed-off-by:
N
Michal Privoznik
<
mprivozn@redhat.com
>
上级
95576b4d
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
257 addition
and
0 deletion
+257
-0
src/security/security_dac.c
src/security/security_dac.c
+257
-0
未找到文件。
src/security/security_dac.c
浏览文件 @
67232478
...
...
@@ -68,6 +68,137 @@ struct _virSecurityDACCallbackData {
virSecurityLabelDefPtr
secdef
;
};
typedef
struct
_virSecurityDACChownItem
virSecurityDACChownItem
;
typedef
virSecurityDACChownItem
*
virSecurityDACChownItemPtr
;
struct
_virSecurityDACChownItem
{
const
char
*
path
;
const
virStorageSource
*
src
;
uid_t
uid
;
gid_t
gid
;
};
typedef
struct
_virSecurityDACChownList
virSecurityDACChownList
;
typedef
virSecurityDACChownList
*
virSecurityDACChownListPtr
;
struct
_virSecurityDACChownList
{
virSecurityDACDataPtr
priv
;
virSecurityDACChownItemPtr
*
items
;
size_t
nItems
;
};
virThreadLocal
chownList
;
static
int
virSecurityDACChownListAppend
(
virSecurityDACChownListPtr
list
,
const
char
*
path
,
const
virStorageSource
*
src
,
uid_t
uid
,
gid_t
gid
)
{
virSecurityDACChownItemPtr
item
;
if
(
VIR_ALLOC
(
item
)
<
0
)
return
-
1
;
item
->
path
=
path
;
item
->
src
=
src
;
item
->
uid
=
uid
;
item
->
gid
=
gid
;
if
(
VIR_APPEND_ELEMENT
(
list
->
items
,
list
->
nItems
,
item
)
<
0
)
{
VIR_FREE
(
item
);
return
-
1
;
}
return
0
;
}
static
void
virSecurityDACChownListFree
(
void
*
opaque
)
{
virSecurityDACChownListPtr
list
=
opaque
;
size_t
i
;
if
(
!
list
)
return
;
for
(
i
=
0
;
i
<
list
->
nItems
;
i
++
)
VIR_FREE
(
list
->
items
[
i
]);
VIR_FREE
(
list
);
}
/**
* virSecurityDACTransactionAppend:
* @path: Path to chown
* @src: disk source to chown
* @uid: user ID
* @gid: group ID
*
* Appends an entry onto transaction list.
*
* Returns: 1 in case of successful append
* 0 if there is no transaction enabled
* -1 otherwise.
*/
static
int
virSecurityDACTransactionAppend
(
const
char
*
path
,
const
virStorageSource
*
src
,
uid_t
uid
,
gid_t
gid
)
{
virSecurityDACChownListPtr
list
=
virThreadLocalGet
(
&
chownList
);
if
(
!
list
)
return
0
;
if
(
virSecurityDACChownListAppend
(
list
,
path
,
src
,
uid
,
gid
)
<
0
)
return
-
1
;
return
1
;
}
static
int
virSecurityDACSetOwnershipInternal
(
const
virSecurityDACData
*
priv
,
const
virStorageSource
*
src
,
const
char
*
path
,
uid_t
uid
,
gid_t
gid
);
/**
* virSecurityDACTransactionRun:
* @pid: process pid
* @opaque: opaque data
*
* This is the callback that runs in the same namespace as the domain we are
* relabelling. For given transaction (@opaque) it relabels all the paths on
* the list.
*
* Returns: 0 on success
* -1 otherwise.
*/
static
int
virSecurityDACTransactionRun
(
pid_t
pid
ATTRIBUTE_UNUSED
,
void
*
opaque
)
{
virSecurityDACChownListPtr
list
=
opaque
;
size_t
i
;
for
(
i
=
0
;
i
<
list
->
nItems
;
i
++
)
{
virSecurityDACChownItemPtr
item
=
list
->
items
[
i
];
/* TODO Implement rollback */
if
(
virSecurityDACSetOwnershipInternal
(
list
->
priv
,
item
->
src
,
item
->
path
,
item
->
uid
,
item
->
gid
)
<
0
)
return
-
1
;
}
return
0
;
}
/* returns -1 on error, 0 on success */
int
virSecurityDACSetUserAndGroup
(
virSecurityManagerPtr
mgr
,
...
...
@@ -238,6 +369,13 @@ virSecurityDACProbe(const char *virtDriver ATTRIBUTE_UNUSED)
static
int
virSecurityDACOpen
(
virSecurityManagerPtr
mgr
ATTRIBUTE_UNUSED
)
{
if
(
virThreadLocalInit
(
&
chownList
,
virSecurityDACChownListFree
)
<
0
)
{
virReportSystemError
(
errno
,
"%s"
,
_
(
"Unable to initialize thread local variable"
));
return
-
1
;
}
return
0
;
}
...
...
@@ -278,6 +416,113 @@ virSecurityDACPreFork(virSecurityManagerPtr mgr)
return
0
;
}
/**
* virSecurityDACTransactionStart:
* @mgr: security manager
*
* Starts a new transaction. In transaction nothing is chown()-ed until
* TransactionCommit() is called. This is implemented as a list that is
* appended to whenever chown() would be called. Since secdriver APIs
* can be called from multiple threads (to work over different domains)
* the pointer to the list is stored in thread local variable.
*
* Returns 0 on success,
* -1 otherwise.
*/
static
int
virSecurityDACTransactionStart
(
virSecurityManagerPtr
mgr
)
{
virSecurityDACDataPtr
priv
=
virSecurityManagerGetPrivateData
(
mgr
);
virSecurityDACChownListPtr
list
;
list
=
virThreadLocalGet
(
&
chownList
);
if
(
list
)
{
virReportError
(
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Another relabel transaction is already started"
));
return
-
1
;
}
if
(
VIR_ALLOC
(
list
)
<
0
)
return
-
1
;
list
->
priv
=
priv
;
if
(
virThreadLocalSet
(
&
chownList
,
list
)
<
0
)
{
virReportSystemError
(
errno
,
"%s"
,
_
(
"Unable to set thread local variable"
));
VIR_FREE
(
list
);
return
-
1
;
}
return
0
;
}
/**
* virSecurityDACTransactionCommit:
* @mgr: security manager
* @pid: domain's PID
*
* Enters the @pid namespace (usually @pid refers to a domain) and
* performs all the chown()-s on the list. Note that the transaction is
* also freed, therefore new one has to be started after successful
* return from this function. Also it is considered as error if there's
* no transaction set and this function is called.
*
* Returns: 0 on success,
* -1 otherwise.
*/
static
int
virSecurityDACTransactionCommit
(
virSecurityManagerPtr
mgr
ATTRIBUTE_UNUSED
,
pid_t
pid
)
{
virSecurityDACChownListPtr
list
;
int
ret
=
-
1
;
list
=
virThreadLocalGet
(
&
chownList
);
if
(
!
list
)
{
virReportError
(
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"No transaction is set"
));
goto
cleanup
;
}
if
(
virThreadLocalSet
(
&
chownList
,
NULL
)
<
0
)
{
virReportSystemError
(
errno
,
"%s"
,
_
(
"Unable to clear thread local variable"
));
goto
cleanup
;
}
if
(
virProcessRunInMountNamespace
(
pid
,
virSecurityDACTransactionRun
,
list
)
<
0
)
goto
cleanup
;
ret
=
0
;
cleanup:
virSecurityDACChownListFree
(
list
);
return
ret
;
}
/**
* virSecurityDACTransactionAbort:
* @mgr: security manager
*
* Cancels and frees any out standing transaction.
*/
static
void
virSecurityDACTransactionAbort
(
virSecurityManagerPtr
mgr
ATTRIBUTE_UNUSED
)
{
virSecurityDACChownListPtr
list
;
list
=
virThreadLocalGet
(
&
chownList
);
if
(
!
list
)
return
;
if
(
virThreadLocalSet
(
&
chownList
,
NULL
)
<
0
)
VIR_DEBUG
(
"Unable to clear thread local variable"
);
virSecurityDACChownListFree
(
list
);
}
static
int
virSecurityDACSetOwnershipInternal
(
const
virSecurityDACData
*
priv
,
const
virStorageSource
*
src
,
...
...
@@ -287,6 +532,14 @@ virSecurityDACSetOwnershipInternal(const virSecurityDACData *priv,
{
int
rc
;
/* Be aware that this function might run in a separate process.
* Therefore, any driver state changes would be thrown away. */
if
((
rc
=
virSecurityDACTransactionAppend
(
path
,
src
,
uid
,
gid
))
<
0
)
return
-
1
;
else
if
(
rc
>
0
)
return
0
;
VIR_INFO
(
"Setting DAC user and group on '%s' to '%ld:%ld'"
,
NULLSTR
(
src
?
src
->
path
:
path
),
(
long
)
uid
,
(
long
)
gid
);
...
...
@@ -1626,6 +1879,10 @@ virSecurityDriver virSecurityDriverDAC = {
.
preFork
=
virSecurityDACPreFork
,
.
transactionStart
=
virSecurityDACTransactionStart
,
.
transactionCommit
=
virSecurityDACTransactionCommit
,
.
transactionAbort
=
virSecurityDACTransactionAbort
,
.
domainSecurityVerify
=
virSecurityDACVerify
,
.
domainSetSecurityDiskLabel
=
virSecurityDACSetDiskLabel
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录