\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#220: Escalate Privileges in VFS Close Callback}
\date{September 12, 2004}
\author{Colin McCormack, Andreas Kupries, Vince Darley}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#220}&\textbf{Escalate Privileges in VFS Close Callback}\\\hline
Author&

Colin McCormack \tipmail{colin}{sharedtech.dyndns.org}
\par
Andreas Kupries \tipmail{akupries}{shaw.ca}
\par
Vince Darley \tipmail{vincentdarley}{users.sourceforge.net}
\\
Created&Sunday, \(\text{12}^{\text{th}}\) September 2004\\
Type&Project\\
Tcl Version&\(8.7\)\\
State&Draft\\
Vote&Pending\\
Version&\tipversion$Revision: 1.18 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This tip allows the creator and opener of a channel to cast away privileges and have them restored on close, to permit last-minute processing. It is sufficient to resolve a \textit{tclvfs} bug, minimal, and safe.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Abstract}

This tip allows the creator and opener of a channel to cast away privileges and have them restored on close, to permit last-minute processing. It is sufficient to resolve a \textit{tclvfs} bug, minimal, and safe.

\section{Rationale}

\textit{Tclvfs} has a bug \textbf{[1004273]} \textit{Can't read from channel in close callback} [\url{http://sourceforge.net/support/tracker.php?aid=1004273}] that is due in part to the core channel handler behaviour.

The problem is that the user has requested a read-only or write-only channel, but the \textit{tclvfs} close process absolutely requires fuller access to the channel.

Use case one: A user's write-only channel has to be read by close in order to be processed.

The second relevant use case: A user's read-only channel has to be written, i.e. loaded with data, before it is passed to the user.

The first use case can be modelled by the \textit{owner} of a channel (in this case, the \textit{tclvfs} code) by opening it with minimal permissions, handing the channel to a user, then subsequently re-aquiring full possible channel permissions at the point where the channel needs to be closed --- that is, immediately before the \textit{tclvfs} close callback is invoked.

The second use case can be modelled by the \textit{owner} of a channel (in this case, the \textit{tclvfs} code) by opening it with maximal permissions, loading the data, and handing the channel to a user \textbf{after} removing the unwanted permissions from the channel.

\section{Safety}
\begin{itemize}
\item{}
Escalation of privilege is controlled with the Tcl core, and is unavailable to extensions except in their role as vfs implementations.
\item{}
Privilege is only granted to the entity which opened the channel, because only that entity implements the close callback.
\item{}
The creator/opener can't operate with any permissions it could not have obtained at creation/opening time, since they are granted by the OS and not Tcl.
\item{}
Privilege escalation occurs only at a point immediately before the Tcl core is about to completely close the channel, so the privileges can't leak.
\item{}
The operation of releasing privileges only restricts the user of a channel, it cannot be used to reaquire privileges which are not granted by the channel.
\end{itemize}

\section{Proposed Changes}

Immediately prior to invoking the VFS close callback on a channel, Tcl core should set channel's permissions to the maximum possible.

Export a new function as part of the public API which allows a user to remove privileges from channel, but not to add them.

\section{Details}

The signature of the new function is
\begingroup\small\begin{verbatim}
 int Tcl_RemoveChannelMode (Tcl_Interp* interp, Tcl_Channel chan, int mode);

 /* Codes for 'mode', already defined, _not_ new */

 #define TCL_READABLE	(1<<1)
 #define TCL_WRITABLE	(1<<2)
\end{verbatim}
\endgroup

The argument \textit{mode} determines which privilege to release, and is set to one of the two specified codes. It is \textbf{not} a bitset. It is not allowed to release all privileges of the channel, as this would make the channel completely inacessible. Trying to do so will therefore cause the generation of an error, without changing the channel. The function will return a regular Tcl result code, either TCL\_OK, or TCL\_ERROR. If the \textit{interp} argument is set an error message will be left in the interp in the error case. If the \textit{interp} argument is NULL it will be ignored.

\section{History}

This TIP was originally written to allow C code to modify permissions, but this makes the permissions system mean nothing, as a channel's permissions could then be freely modified in an \textit{ad hoc} manner. The TIP now specifies a weaker modification that is still powerful enough to implemenent the desired channel semantics.

\section{Reference Implementation}

A reference implementation will be provided at SourceForge [\url{http://sourceforge.net/support/tracker.php?aid=1057093}].

\section{Comments}

It may be preferable for the new function to be in tclInt.h and therefore in the non-public interfaces (tclvfs already makes use of tclInt.h anyway): TclRemoveChannelMode.

\textit{[ Add more comments on the document here ]}

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
